diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index e4c1529..6a978d4 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -273,7 +273,7 @@ novirtual class CallGenBase: # appended by the caller) are preserved. Idempotent: _apply_auto_addr_arg passes an already-pointer # argument through, so a caller that also ran translate_call_arg does not double-address. def _apply_auto_addr_to_call_args(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, - trans: HT.Translator*, callee_name: str, arg_nodes: list[ast.AST*]*, + trans: HT.Translator*, callee_name: char*, arg_nodes: list[ast.AST*]*, head: mlirlite.Value*, count: int, start_idx: int) -> mlirlite.Value*: """Apply value-reference auto-address (&T / &temp T) to a call's user args; returns the chain head.""" if head is None or count <= 0: return head @@ -305,7 +305,7 @@ novirtual class CallGenBase: mlirlite.value_set_next(new_tail, cur) return new_head - def _lookup_module_sha1(self, mod_name: str) -> str: + def _lookup_module_sha1(self, mod_name: char*) -> str: """Resolve a module name (or an already-resolved SHA1) to a SHA1; None if absent. Re-export entries may store the defining SHA1 directly, so a 16-hex input is @@ -323,11 +323,11 @@ novirtual class CallGenBase: if is_hex != 0: return mod_name return StubMergerStore.LookupSha1ByModName(mod_name) - def _lookup_module_sha1_suffix(self, mod_suffix: str) -> str: + def _lookup_module_sha1_suffix(self, mod_suffix: char*) -> str: """Look up a module SHA1 by suffix (e.g. "__types" matches "mlirlite.__types") for relative imports, via StubMerger.LookupSha1ByModNameSuffix.""" return StubMergerStore.LookupSha1ByModNameSuffix(mod_suffix) - def _module_package_from_sha1(self, pool: memhub.MemBuddy*, mod_sha1: str) -> str: + def _module_package_from_sha1(self, pool: memhub.MemBuddy*, mod_sha1: char*) -> str: """Compute the module's package name (directory part, '/' to '.') from the SHA1 store's rel_path""" if pool is None or mod_sha1 is None: return None rel_arr_ptr: bytes = StubMergerStore.GetSha1StoreRelArrPtr() @@ -338,7 +338,7 @@ novirtual class CallGenBase: sidx: sizet = sizet(i) * 17 if string.strcmp(sha1_arr_ptr + sidx, mod_sha1) != 0: continue ridx: sizet = sizet(i) * StubMerger.MAX_REL_PATH_LEN - rel: str = rel_arr_ptr + ridx + rel: char* = rel_arr_ptr + ridx # Includes are registered with a workspace-relative path ("includes/ast/__init__.vp") # because the scan root is the workspace, while the module name drops that prefix # ("ast", "ast.lexer"). Dropping it here too keeps re-export resolution (`from .lexer @@ -346,11 +346,11 @@ novirtual class CallGenBase: rel_off: sizet = 0 if string.strncmp(rel, "includes/", 9) == 0: rel_off = 9 rel = rel + rel_off - last_slash: str = string.strrchr(rel, 47) # 47 = ord('/') + last_slash: char* = string.strrchr(rel, 47) # 47 = ord('/') if last_slash is None: return None pkg_len: sizet = sizet(uint64(last_slash) - uint64(rel)) if pkg_len == 0: return None - pkg_buf: str = pool.alloc(pkg_len + 1) + pkg_buf: char* = pool.alloc(pkg_len + 1) if pkg_buf is None: return None for pi in range(int(pkg_len)): if rel[pi] == '/': pkg_buf[pi] = '.' @@ -360,7 +360,7 @@ novirtual class CallGenBase: return None - def _lookup_reexport_from_vpi(self, pool: memhub.MemBuddy*, mod_sha1: str, func_name: str, allow_star: int = 1) -> str: + def _lookup_reexport_from_vpi(self, pool: memhub.MemBuddy*, mod_sha1: char*, func_name: char*, allow_star: int = 1) -> str: """On a re-export table miss, parse the module's .vpi from-import statements to locate the defining module (the table may be empty since it is only populated during full translation). allow_star=0 skips `from X import *` candidates: they are unverified hints (the caller must check them), and a CLASS owner must never be taken from one -- nearly every file star-imports @@ -368,12 +368,12 @@ novirtual class CallGenBase: forward-declared as "stdint.TypeGenErr" this way, then every vpi/text.ll lookup missed).""" if pool is None or mod_sha1 is None or func_name is None: return None # accumulate star-import candidates (space-separated); caller validates each - star_cands: str = None + star_cands: char* = None star_cands_len: sizet = 0 - temp_dir: str = self.Gen.TypeGenBase.get_temp_dir() + temp_dir: char* = self.Gen.TypeGenBase.get_temp_dir() if temp_dir is None: return None td_len: sizet = string.strlen(temp_dir) - vpi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, mod_sha1, "vpi") + vpi_path: char* = StubMergerCollect._sliced_path(temp_dir, td_len, mod_sha1, "vpi") if vpi_path is None: return None READ_SZ: sizet = 1048576 buf: bytes = stdlib.malloc(READ_SZ) @@ -436,7 +436,7 @@ novirtual class CallGenBase: if allow_star == 0: continue star_dot: int = 0 if buf[mod_start] == '.': star_dot = 1 - star_buf: str = pool.alloc(mod_end - mod_start + 1) + star_buf: char* = pool.alloc(mod_end - mod_start + 1) if star_buf is not None: si2: sizet = 0 while mod_start + si2 < mod_end: @@ -446,16 +446,16 @@ novirtual class CallGenBase: while star_buf[0] == '.': star_buf = star_buf + 1 if string.strlen(star_buf) > 0: if star_dot != 0: - spkg: str = self._module_package_from_sha1(pool, mod_sha1) + spkg: char* = self._module_package_from_sha1(pool, mod_sha1) if spkg is not None: srl: sizet = string.strlen(spkg) + string.strlen(star_buf) + 2 - sres: str = pool.alloc(srl) + sres: char* = pool.alloc(srl) if sres is not None: viperlib.snprintf(sres, srl, "%s.%s", spkg, star_buf) star_buf = sres # accumulate candidates (space-separated) sbl: sizet = string.strlen(star_buf) - new_cands: str = pool.alloc(star_cands_len + sbl + 2) + new_cands: char* = pool.alloc(star_cands_len + sbl + 2) if new_cands is not None: if star_cands is not None and star_cands_len > 0: string.strcpy(new_cands, star_cands) @@ -492,7 +492,7 @@ novirtual class CallGenBase: # hit: parse module name (leading dot -> relative, add pkg prefix) has_dot: int = 0 if buf[mod_start] == '.': has_dot = 1 - mod_buf: str = pool.alloc(mod_end - mod_start + 1) + mod_buf: char* = pool.alloc(mod_end - mod_start + 1) if mod_buf is None: stdlib.free(buf) return None @@ -506,12 +506,12 @@ novirtual class CallGenBase: stdlib.free(buf) return None if has_dot != 0: - pkg: str = self._module_package_from_sha1(pool, mod_sha1) + pkg: char* = self._module_package_from_sha1(pool, mod_sha1) if pkg is None: stdlib.free(buf) return None rl: sizet = string.strlen(pkg) + string.strlen(mod_buf) + 2 - res: str = pool.alloc(rl) + res: char* = pool.alloc(rl) if res is None: stdlib.free(buf) return None @@ -530,7 +530,7 @@ novirtual class CallGenBase: return None - def register_cexport_func(self, sha1: str, func_name: str) -> int: + def register_cexport_func(self, sha1: char*, func_name: char*) -> int: """Register a ExportT function into the global table (single source of truth in Gen.CallGenBase)""" if self.Gen is None or sha1 is None or func_name is None: return 0 if self.Gen.CallGenBase.CexportSha1Arr is None: @@ -552,7 +552,7 @@ novirtual class CallGenBase: return 0 - def is_cexport_func(self, sha1: str, func_name: str) -> int: + def is_cexport_func(self, sha1: char*, func_name: char*) -> int: """Whether (sha1, func_name) is a ExportT function (reads the Gen.CallGenBase source of truth), falling back to the vpi return annotation on a registry miss.""" if self.Gen is None or sha1 is None or func_name is None: return 0 if self.Gen.CallGenBase.CexportSha1Arr is not None: @@ -566,7 +566,7 @@ novirtual class CallGenBase: # RegisterStaticSymbol / IsStaticSymbol - static symbol registry: the four # syntaxes all normalize to t.StaticT; meaning = no cross-module use. - def RegisterStaticSymbol(self, sha1: str, name: str) -> int: + def RegisterStaticSymbol(self, sha1: char*, name: char*) -> int: """Register a static symbol (defining module SHA1 + symbol name); 1=registered (idempotent) / 0=failure""" if self.Gen is None or sha1 is None or name is None: return 0 if self.Gen.CallGenBase.StaticSha1Arr is None: @@ -594,7 +594,7 @@ novirtual class CallGenBase: return 0 - def IsStaticSymbol(self, sha1: str, name: str) -> int: + def IsStaticSymbol(self, sha1: char*, name: char*) -> int: """Whether (sha1, name) is a registered static symbol, the cross-module reference blocker; pairs (sha1, name) exactly to avoid same-name mistakes.""" if self.Gen is None or sha1 is None or name is None: return 0 if self.Gen.CallGenBase.StaticSha1Arr is None: return 0 @@ -606,7 +606,7 @@ novirtual class CallGenBase: return 0 - def _is_cexport_func_from_vpi(self, sha1: str, func_name: str) -> int: + def _is_cexport_func_from_vpi(self, sha1: char*, func_name: char*) -> int: """Whether the vpi declares a bare-name function (`export def` / `extern def` / legacy ExportT).""" if sha1 is None or func_name is None: return 0 if self.Gen is None or self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen <= 0: return 0 @@ -614,45 +614,45 @@ novirtual class CallGenBase: # New vpi carries the storage marker as the `export`/`extern` prefix, not in the # return annotation; without this, cross-module calls mangle the name and link fails. if VpiReader._lookup_vpi_bare(sha1, None, func_name) != 0: return 1 - cexp_annot: str = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) + cexp_annot: char* = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) if cexp_annot is None: return 0 if string.strstr(cexp_annot, "ExportT") is not None: return 1 return 0 - def _is_state_func_from_vpi(self, pool: memhub.MemBuddy*, sha1: str, func_name: str) -> int: + def _is_state_func_from_vpi(self, pool: memhub.MemBuddy*, sha1: char*, func_name: char*) -> int: """Whether the vpi declares a bare-name external C function (`extern def` / legacy State).""" if pool is None or sha1 is None or func_name is None: return 0 if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir) # `extern def` prefix (current vpi) => bare C symbol name. if VpiReader._lookup_vpi_bare(sha1, None, func_name) != 0: return 1 - state_annot: str = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) + state_annot: char* = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) if state_annot is None: return 0 # ret annotation contains "State" -> external C function if string.strstr(state_annot, "State") is not None: return 1 return 0 - def _lookup_mod_sha1(self, pool: memhub.MemBuddy*, from_imports: str, class_name: str, allow_star_fallback: int = 1) -> str: + def _lookup_mod_sha1(self, pool: memhub.MemBuddy*, from_imports: char*, class_name: char*, allow_star_fallback: int = 1) -> str: """Look up the SHA1 of the module owning a class found in from_imports; None if not found. allow_star_fallback=0 disables star-import fallback.""" - mod_name_raw: str = self.Gen.ImportsGen.lookup_from_import(from_imports, class_name, allow_star_fallback) + mod_name_raw: char* = self.Gen.ImportsGen.lookup_from_import(from_imports, class_name, allow_star_fallback) if mod_name_raw is None: return None return self._lookup_sha1_from_modname_raw(pool, mod_name_raw) - def _lookup_sha1_from_modname_raw(self, pool: memhub.MemBuddy*, mod_name_raw: str) -> str: + def _lookup_sha1_from_modname_raw(self, pool: memhub.MemBuddy*, mod_name_raw: char*) -> str: """Look up SHA1 from a raw module name; None if not found""" # find module-name end (space/null/':' alias sep), copy into a new buffer mod_len: sizet = 0 while mod_name_raw[mod_len] != ' ' and mod_name_raw[mod_len] != '\0' and mod_name_raw[mod_len] != ':': mod_len += 1 - mod_name_buf: str = pool.alloc(mod_len + 1) + mod_name_buf: char* = pool.alloc(mod_len + 1) if mod_name_buf is None: return None for mi in range(int(mod_len)): mod_name_buf[mi] = mod_name_raw[mi] mod_name_buf[mod_len] = '\0' # strip leading dots of relative import - base_mod: str = mod_name_buf + base_mod: char* = mod_name_buf while base_mod[0] == '.': base_mod = base_mod + 1 - sha1: str = self._lookup_module_sha1(base_mod) + sha1: char* = self._lookup_module_sha1(base_mod) if sha1 is None: sha1 = self._lookup_module_sha1_suffix(base_mod) return sha1 @@ -675,7 +675,7 @@ novirtual class CallGenBase: p_cur = mlirlite.param_get_next(p_cur) return mlirlite.Func(pool, f_ref.RetTy, pn_head, p_cnt) - def find_func_in_module(self, mod: mlirlite.LLVMModule*, name: str, owner_sha1: str = None) -> mlirlite.Function*: + def find_func_in_module(self, mod: mlirlite.LLVMModule*, name: char*, owner_sha1: char* = None) -> mlirlite.Function*: """Find a function by name in the module's function list: exact then suffix match, honoring owner_sha1 for same-module priority.""" if mod is None or name is None: return None name_len: sizet = string.strlen(name) @@ -686,7 +686,7 @@ novirtual class CallGenBase: declare_hit: mlirlite.Function* = None any_hit: mlirlite.Function* = None while cur is not None: - cur_name: str = mlirlite.function_get_name(cur) + cur_name: char* = mlirlite.function_get_name(cur) if cur_name is not None: # fast path: skip strcmp when first chars differ (mangled names start # with sha1 hex, bare names with letters/underscore) @@ -725,7 +725,7 @@ novirtual class CallGenBase: # _ensure_method_declare: create a declare in the current module when the stub is missing - def _ensure_method_declare(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, call_name: str, ret_ty: mlirlite.LLVMType*, param_head: mlirlite.Value*, param_count: int): + def _ensure_method_declare(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, call_name: char*, ret_ty: mlirlite.LLVMType*, param_head: mlirlite.Value*, param_count: int): """Create a declare for a cross-module method call, appending missing params to an existing shorter declare (defines are left untouched).""" if pool is None or mod is None or call_name is None: return # list-walk sentinel (fail-fast): an unbounded walk would loop forever if a @@ -786,9 +786,9 @@ novirtual class CallGenBase: func.IsDeclared = 1 # Prefer definition-side param types (from {sha1}.{cls}.{method} vpi # annotations): wider ints win, pointers always use the definition side. - sha1_d: str = None - cls_d: str = None - meth_d: str = None + sha1_d: char* = None + cls_d: char* = None + meth_d: char* = None if call_name is not None: # SHA1 prefix via single source GenApi.sha1_prefix_len (no hardcoded 17/16) sha1_pfx_d: int = GenApi.sha1_prefix_len(call_name) @@ -799,9 +799,9 @@ novirtual class CallGenBase: string.strncpy(sha1_buf_d, call_name, pfx_len_d - 1) sha1_buf_d[pfx_len_d - 1] = '\0' sha1_d = sha1_buf_d - rest_d: str = call_name + pfx_len_d + rest_d: char* = call_name + pfx_len_d # take the last '.': method has no dot; the first would truncate module-qualified args - dot2_d: str = string.strrchr(rest_d, '.') + dot2_d: char* = string.strrchr(rest_d, '.') if dot2_d is not None: cls_len_d: sizet = uint64(dot2_d) - uint64(rest_d) if cls_len_d > 0: @@ -812,7 +812,7 @@ novirtual class CallGenBase: cls_d = cls_buf_d meth_d = dot2_d + 1 else: meth_d = rest_d - prm_annots_d: str = None + prm_annots_d: char* = None if sha1_d is not None and meth_d is not None: prm_annots_d = self._vpi_method_param_annot(pool, sha1_d, cls_d, meth_d) i32_ty_d: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_d: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -853,8 +853,8 @@ novirtual class CallGenBase: def _call_ty_equal(self, pool: memhub.MemBuddy*, a: mlirlite.LLVMType*, b: mlirlite.LLVMType*) -> int: """1 when both types have the same LLVM text (the canonical form used for emission).""" if a is None or b is None: return 0 - ta: str = self.Gen.ExprGenBase._type_text(pool, a) - tb: str = self.Gen.ExprGenBase._type_text(pool, b) + ta: char* = self.Gen.ExprGenBase._type_text(pool, a) + tb: char* = self.Gen.ExprGenBase._type_text(pool, b) if ta is None or tb is None: return 0 if string.strcmp(ta, tb) == 0: return 1 return 0 @@ -862,11 +862,11 @@ novirtual class CallGenBase: # _path_tail_is - 1 when the last `.`-separated segment of path equals name. # Discriminates `mod.Class.func()` (path tail = the class) from `mod.func()` (path tail = the # module) when a suffix lookup finds a dotted method symbol. - def _path_tail_is(self, path: str, name: str) -> int: + def _path_tail_is(self, path: char*, name: char*) -> int: """1 when the last segment of path equals name.""" if path is None or name is None: return 0 - dot: str = string.strrchr(path, 46) - tail: str = path + dot: char* = string.strrchr(path, 46) + tail: char* = path if dot is not None: tail = dot + 1 if tail[0] == '\0': return 0 if string.strcmp(tail, name) == 0: return 1 @@ -880,7 +880,7 @@ novirtual class CallGenBase: if func is None: return 0 p: mlirlite.Param* = mlirlite.function_get_param_head(func) if p is None: return 0 - nm: str = mlirlite.param_get_name(p) + nm: char* = mlirlite.param_get_name(p) if nm is None: return 1 if string.strcmp(nm, "self") == 0: return 1 if string.strcmp(nm, "cls") == 0: return 1 @@ -894,7 +894,7 @@ novirtual class CallGenBase: # not accept, and only the MLIR verifier notices. Once the declare/definition exists it is # the authority: coerce each argument to its parameter type, use its return type, and fail # fast when a cross-module call site resolved a conflicting return type. - def _call_symbol_ret_ty(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, call_name: str, + def _call_symbol_ret_ty(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, call_name: char*, ret_ty: mlirlite.LLVMType*, node: ast.AST* = None) -> mlirlite.LLVMType*: """Return type to emit for this call: the callee symbol's, validated against ret_ty.""" if mod is None or call_name is None: return ret_ty @@ -922,7 +922,7 @@ novirtual class CallGenBase: # Positional alignment over the fixed params; a variadic callee's extra arguments (already # promoted to the C ABI) are left untouched. def _conform_call_args(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, - call_name: str, head: mlirlite.Value*, node: ast.AST* = None, + call_name: char*, head: mlirlite.Value*, node: ast.AST* = None, trans: HT.Translator* = None) -> mlirlite.Value*: """Rebuild the argument chain with every fixed argument coerced to its parameter type.""" if head is None or call_name is None or mod is None: return head @@ -962,7 +962,7 @@ novirtual class CallGenBase: # `X*` / `X**` / `module.Class` / 裸类名 / 内建名 / typedef。 # 只用最基础的字符串操作,不依赖 VpiReader 的多分支分段解析器:自举时该解析器可能 # 误编译,让一个已注册的类解析失败。无法判定时返回 None,由后续完整解析器继续处理。 - def _resolve_vpi_annot_direct(self, pool: memhub.MemBuddy*, annot: str) -> mlirlite.LLVMType*: + def _resolve_vpi_annot_direct(self, pool: memhub.MemBuddy*, annot: char*) -> mlirlite.LLVMType*: """解析 vpi 注解里的指针写法:`X*` / `X**` / `const X*` / `module.Class`。 不递归:先把 `const` / `volatile` 前缀剥掉,再统计尾部 `*` 的层数, 最后只做一次类/枚举/typedef 查找并按层数包 Ptr。""" @@ -991,8 +991,8 @@ novirtual class CallGenBase: if nm_buf is None: return None string.strncpy(nm_buf, annot + st_i, end_i - st_i) nm_buf[end_i - st_i] = '\0' - dot_n: str = string.strrchr(nm_buf, '.') - cls_n: str = nm_buf + dot_n: char* = string.strrchr(nm_buf, '.') + cls_n: char* = nm_buf if dot_n is not None: cls_n = dot_n + 1 base_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_n) if base_ty is None: base_ty = GenApi.get_enum_base_type(cls_n) @@ -1006,7 +1006,7 @@ novirtual class CallGenBase: # (`GSList[Param]*`, `dict[str, X]*`) by specializing it on demand. VpiReader's string # resolver handles markers/named types only, so without this a generic return type falls # through to the i32 placeholder (现场: mlirlite.function_get_params -> GSList[Param]*). - def _resolve_generic_annot_str(self, trans: HT.Translator*, pool: memhub.MemBuddy*, annot: str) -> mlirlite.LLVMType*: + def _resolve_generic_annot_str(self, trans: HT.Translator*, pool: memhub.MemBuddy*, annot: char*) -> mlirlite.LLVMType*: """Specialize `Base[Arg, ...]` (+ trailing '*') from an annotation string; None if not applicable.""" if trans is None or pool is None or annot is None: return None a_len: sizet = string.strlen(annot) @@ -1031,7 +1031,7 @@ novirtual class CallGenBase: if lb >= end_i - 1: return None base_len: sizet = lb - st_i if base_len == 0: return None - base_buf: str = pool.alloc(base_len + 1) + base_buf: char* = pool.alloc(base_len + 1) if base_buf is None: return None string.strncpy(base_buf, annot + st_i, base_len) base_buf[base_len] = '\0' @@ -1047,7 +1047,7 @@ novirtual class CallGenBase: while seg_s < seg_e and annot[seg_s] == ' ': seg_s += 1 while seg_e > seg_s and annot[seg_e - 1] == ' ': seg_e -= 1 if seg_e > seg_s: - ab: str = pool.alloc(seg_e - seg_s + 1) + ab: char* = pool.alloc(seg_e - seg_s + 1) if ab is None: return None string.strncpy(ab, annot + seg_s, seg_e - seg_s) ab[seg_e - seg_s] = '\0' @@ -1057,7 +1057,7 @@ novirtual class CallGenBase: elif annot[ai] == ']': depth_g -= 1 ai += 1 if len(ta_list) == 0: return None - spec: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_buf, ta_list) + spec: char* = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_buf, ta_list) if spec is None: return None ty: mlirlite.LLVMType* = GenApi.get_struct_type(spec) if ty is None: ty = GenApi.get_enum_base_type(spec) @@ -1068,7 +1068,7 @@ novirtual class CallGenBase: k_l += 1 return ty - def _lookup_method_ret_ty_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: str, cls_name: str, method_name: str, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: + def _lookup_method_ret_ty_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: char*, cls_name: char*, method_name: char*, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: """Get a method return type from the vpi stub annotation cache; None on miss""" if pool is None or cls_sha1 is None or method_name is None: return None # lazy import inside the function: VpiReader imports HandlesExprCall, a top-level import would cycle @@ -1077,7 +1077,7 @@ novirtual class CallGenBase: # on-demand load: read {temp_dir}/{sha1[0:2]}/{sha1}.vpi on cache miss, # covering method calls whose stub is not yet injected. if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) - annot: str = VpiReader._lookup_vpi_ret_annot(cls_sha1, cls_name, method_name) + annot: char* = VpiReader._lookup_vpi_ret_annot(cls_sha1, cls_name, method_name) # A re-export facade such as `io.vp` (`from _io import *`) has no own `def`; # the annotation is stored in the defining module's vpi. Follow the re-export # entry to that module before giving up. @@ -1098,7 +1098,7 @@ novirtual class CallGenBase: if ret_ty is None: ret_ty = self._resolve_generic_annot_str(trans, pool, annot) return ret_ty - def _vpi_module_defines(self, mod_sha1: str, func_name: str) -> int: + def _vpi_module_defines(self, mod_sha1: char*, func_name: char*) -> int: """Return 1 when the module's .vpi declares a module-level function with this name.""" if mod_sha1 is None or func_name is None: return 0 if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: @@ -1106,7 +1106,7 @@ novirtual class CallGenBase: if VpiReader._lookup_vpi_ret_annot(mod_sha1, None, func_name) is not None: return 1 return 0 - def _is_reexport_owner(self, pool: memhub.MemBuddy*, mod_sha1: str, func_name: str, owner_full_name: str) -> int: + def _is_reexport_owner(self, pool: memhub.MemBuddy*, mod_sha1: char*, func_name: char*, owner_full_name: char*) -> int: """Return 1 when owner_full_name belongs to a re-export source of mod_sha1. A module-qualified call on a facade (e.g. `io.ExpandEnvironmentPath`) @@ -1122,7 +1122,7 @@ novirtual class CallGenBase: osuf: sizet = own_len - fn_len if owner_full_name[osuf - 1] != '.': return 0 if string.strcmp(owner_full_name + osuf, func_name) != 0: return 0 - rr_src: str = self.Gen.ImportsGen.lookup_reexport_call(mod_sha1, func_name) + rr_src: char* = self.Gen.ImportsGen.lookup_reexport_call(mod_sha1, func_name) if rr_src is None: rr_src = self._lookup_reexport_from_vpi(pool, mod_sha1, func_name) if rr_src is None: return 0 total: sizet = string.strlen(rr_src) @@ -1134,17 +1134,17 @@ novirtual class CallGenBase: while ri < total and rr_src[ri] != ' ': ri += 1 seg_len: sizet = ri - seg_start if seg_len == 0: continue - seg_buf: str = pool.alloc(seg_len + 1) + seg_buf: char* = pool.alloc(seg_len + 1) if seg_buf is None: continue string.strncpy(seg_buf, rr_src + seg_start, seg_len) seg_buf[seg_len] = '\0' - cand_sha1: str = self._lookup_module_sha1(seg_buf) + cand_sha1: char* = self._lookup_module_sha1(seg_buf) if cand_sha1 is None: cand_sha1 = self._lookup_module_sha1_suffix(seg_buf) if cand_sha1 is not None: if string.strncmp(owner_full_name, cand_sha1, 16) == 0 and own_len > 17 and owner_full_name[16] == '.': return 1 return 0 - def _lookup_reexport_ret_ty(self, pool: memhub.MemBuddy*, cls_sha1: str, cls_name: str, method_name: str, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: + def _lookup_reexport_ret_ty(self, pool: memhub.MemBuddy*, cls_sha1: char*, cls_name: char*, method_name: char*, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: """Resolve a module-level function's return type through re-export entries. The facade vpi has no `def`; the annotation belongs to the defining module. @@ -1154,7 +1154,7 @@ novirtual class CallGenBase: """ if depth >= 4 or pool is None or cls_sha1 is None or method_name is None: return None if cls_name is not None: return None - rr_src: str = self.Gen.ImportsGen.lookup_reexport_call(cls_sha1, method_name) + rr_src: char* = self.Gen.ImportsGen.lookup_reexport_call(cls_sha1, method_name) if rr_src is None: rr_src = self._lookup_reexport_from_vpi(pool, cls_sha1, method_name) if rr_src is None: return None total: sizet = string.strlen(rr_src) @@ -1166,18 +1166,18 @@ novirtual class CallGenBase: while ri < total and rr_src[ri] != ' ': ri += 1 seg_len: sizet = ri - seg_start if seg_len == 0: continue - seg_buf: str = pool.alloc(seg_len + 1) + seg_buf: char* = pool.alloc(seg_len + 1) if seg_buf is None: continue string.strncpy(seg_buf, rr_src + seg_start, seg_len) seg_buf[seg_len] = '\0' - rr_sha1: str = self._lookup_module_sha1(seg_buf) + rr_sha1: char* = self._lookup_module_sha1(seg_buf) if rr_sha1 is None: rr_sha1 = self._lookup_module_sha1_suffix(seg_buf) if rr_sha1 is not None: ty: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, rr_sha1, cls_name, method_name, trans, depth + 1) if ty is not None: return ty return None - def _vpi_escape_packed(self, sha1: str, cls_name: str, method_name: str) -> int: + def _vpi_escape_packed(self, sha1: char*, cls_name: char*, method_name: char*) -> int: """跨模块逃逸摘要查询(v3):按 (定义模块 sha1, Class?, method) 查 .vpi 缓存;0=无摘要。 用"本模块已加载"备忘包住 _ensure_vpi_ret_annot_loaded(其内部是 O(N) 前缀判定): @@ -1194,7 +1194,7 @@ novirtual class CallGenBase: # lookup_escape_dir_via_vpi - 跨模块声明式指令契约(@life(escape(...)) / @life(noescape(...)))。 # 本文件指令表按文件重置,跨模块调用点必为空,只能靠 .vpi 行尾的 esce=/escn= 传递; # noescape != 0 取"强制不逃逸位",否则取"强制逃逸位"。0 = 无该标注(含该模块未加载过)。 - def lookup_escape_dir_via_vpi(self, cls_sha1: str, class_name: str, func_name: str, noescape: int) -> int: + def lookup_escape_dir_via_vpi(self, cls_sha1: char*, class_name: char*, func_name: char*, noescape: int) -> int: """对方模块 .vpi 里落的契约掩码;0 = 无该标注""" if func_name is None or cls_sha1 is None: return 0 return VpiReader._lookup_vpi_escape_dir(cls_sha1, class_name, func_name, noescape) @@ -1203,7 +1203,7 @@ novirtual class CallGenBase: # 与 escape/noescape 同一条 .vpi 通道(行尾 escr=);0 = 无声明(含该模块未加载过)。 # 注意:本查询可能在调用点**之前**(life_of_expr 判右值生命期)发生,不能假定调用点的 # 逃逸查询已把对方 vpi 载入,故这里自己走一次"本模块已加载"备忘 + 按需加载。 - def lookup_ret_kind_via_vpi(self, cls_sha1: str, class_name: str, func_name: str) -> int: + def lookup_ret_kind_via_vpi(self, cls_sha1: char*, class_name: char*, func_name: char*) -> int: """对方模块 .vpi 里落的 ret_kind;0 = 无声明""" if func_name is None or cls_sha1 is None: return 0 if VpiReader._vpi_escape_module_loaded(cls_sha1) == 0: @@ -1217,7 +1217,7 @@ novirtual class CallGenBase: VpiReader._vpi_escape_mark_module(cls_sha1) return VpiReader._lookup_vpi_escape_dir(cls_sha1, class_name, func_name, 2) - def lookup_escape_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: str, cls_name: str, method_name: str) -> int: + def lookup_escape_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: char*, cls_name: char*, method_name: char*) -> int: """跨模块逃逸摘要(v3):本类 + MRO 祖先各自的模块 sha1 依次查 .vpi,返回打包值(0=无摘要)。 本文件的摘要表按文件重置,跨模块调用点上必为空,只能靠 .vpi 传递; @@ -1230,16 +1230,16 @@ novirtual class CallGenBase: mro: sizet* = self.Gen.StructGen.get_mro_chain(pool, cls_name) mi: int = 1 while mro is not None and mro[mi] != 0: - anc: str = rawptr(mro[mi]) + anc: char* = rawptr(mro[mi]) if anc is not None and string.strcmp(anc, cls_name) != 0: - sha_a: str = self.Gen.StructGen.get_struct_sha1(anc) + sha_a: char* = self.Gen.StructGen.get_struct_sha1(anc) if sha_a is not None: pa: int = self._vpi_escape_packed(sha_a, anc, method_name) if pa != 0: return pa mi += 1 return 0 - def _vpi_willfree(self, sha1: str, cls_name: str, method_name: str) -> int: + def _vpi_willfree(self, sha1: char*, cls_name: char*, method_name: char*) -> int: """跨模块 willFree 标注查询(P2):按 (定义模块 sha1, Class?, method) 查 .vpi 缓存;0=无标注。 与逃逸摘要共用"本模块已加载"备忘:_ensure_vpi_ret_annot_loaded 的单一入口会把 @@ -1251,7 +1251,7 @@ novirtual class CallGenBase: VpiReader._vpi_escape_mark_module(sha1) return VpiReader._lookup_vpi_willfree(sha1, cls_name, method_name) - def lookup_escape_clears_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: str, class_name: str, func_name: str, cargs: list[ast.AST*]*, can: sizet, param_base: int) -> int: + def lookup_escape_clears_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: char*, class_name: char*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, param_base: int) -> int: """跨模块常量特化:把实参字面量装进常量环境,再向 vpi 缓存要"该清掉的位掩码";0 = 无命中 跨模块拿不到被调者函数体(只有 .vpi),所以用落盘的守卫表(`escg=`)而不是重算摘要。 @@ -1262,7 +1262,7 @@ novirtual class CallGenBase: if fenv is None: return 0 return VpiReader._lookup_vpi_escape_clears(cls_sha1, class_name, func_name, fenv) - def lookup_willfree_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: str, cls_name: str, method_name: str) -> int: + def lookup_willfree_via_vpi(self, pool: memhub.MemBuddy*, cls_sha1: char*, cls_name: char*, method_name: char*) -> int: """跨模块 willFree 掩码(P2):本类 + MRO 祖先各自的模块 sha1 依次查 .vpi;0=无标注""" if method_name is None: return 0 if cls_sha1 is not None: @@ -1272,9 +1272,9 @@ novirtual class CallGenBase: mro: sizet* = self.Gen.StructGen.get_mro_chain(pool, cls_name) mi: int = 1 while mro is not None and mro[mi] != 0: - anc: str = rawptr(mro[mi]) + anc: char* = rawptr(mro[mi]) if anc is not None and string.strcmp(anc, cls_name) != 0: - sha_a: str = self.Gen.StructGen.get_struct_sha1(anc) + sha_a: char* = self.Gen.StructGen.get_struct_sha1(anc) if sha_a is not None: pa: int = self._vpi_willfree(sha_a, anc, method_name) if pa != 0: return pa @@ -1282,7 +1282,7 @@ novirtual class CallGenBase: return 0 # _vpi_method_param_annot: on-demand lookup of the vpi param annotation string - def _vpi_method_param_annot(self, pool: memhub.MemBuddy*, cls_sha1: str, cls_name: str, method_name: str) -> str: + def _vpi_method_param_annot(self, pool: memhub.MemBuddy*, cls_sha1: char*, cls_name: char*, method_name: char*) -> str: """Load and query the vpi parameter annotation string on demand; None on miss""" if pool is None or cls_sha1 is None or cls_name is None or method_name is None: return None # on-demand load: read {temp_dir}/{sha1[0:2]}/{sha1}.vpi on cache miss @@ -1290,7 +1290,7 @@ novirtual class CallGenBase: return VpiReader._lookup_vpi_param_annots(cls_sha1, cls_name, method_name) # _vpi_resolve_param_annot_ty: parse a vpi param annotation segment into LLVMType - def _vpi_resolve_param_annot_ty(self, pool: memhub.MemBuddy*, seg: str, src_sha1: str = None) -> mlirlite.LLVMType*: + def _vpi_resolve_param_annot_ty(self, pool: memhub.MemBuddy*, seg: char*, src_sha1: char* = None) -> mlirlite.LLVMType*: """Parse a single vpi parameter annotation segment into an LLVMType; None on failure""" if pool is None or seg is None: return None i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -1301,7 +1301,7 @@ novirtual class CallGenBase: # _special_method_ret_ty: fixed return types for compiler built-in special methods # ============================================================ - def _special_method_ret_ty(self, pool: memhub.MemBuddy*, class_name: str, method_name: str) -> mlirlite.LLVMType*: + def _special_method_ret_ty(self, pool: memhub.MemBuddy*, class_name: char*, method_name: char*) -> mlirlite.LLVMType*: """Fixed return type for compiler builtin special methods; None for non-special ones""" if pool is None or method_name is None: return None if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0: return mlirlite.Void(pool) @@ -1315,7 +1315,7 @@ novirtual class CallGenBase: # _fail_method_ret_ty: ERROR + abort when the method return type cannot be resolved # ============================================================ - def _fail_method_ret_ty(self, method_name: str, node: ast.AST* = None, cls: str = None, anc: str = None, sha1: str = None, pool: memhub.MemBuddy* = None) -> mlirlite.LLVMType*: + def _fail_method_ret_ty(self, method_name: char*, node: ast.AST* = None, cls: char* = None, anc: char* = None, sha1: char* = None, pool: memhub.MemBuddy* = None) -> mlirlite.LLVMType*: """Fail fast when a method return type cannot be resolved precisely (module function, text.ll define, then vpi cache); never default to i32.""" # NOTE: VLogger.error terminates the process in batch mode (sys.exit(1)), so the whole # report must be a SINGLE call -- anything after it is dead code (this is why a separate @@ -1324,30 +1324,30 @@ novirtual class CallGenBase: # Reports: receiver class, its registered struct sha1, the class/sha1 actually used for # the lookup (MRO fallback candidate), whether that module's text.ll exists, and the raw # vpi return-annotation string if the cache holds one. - c_cls: str = cls + c_cls: char* = cls if c_cls is None: c_cls = "?" - c_anc: str = anc + c_anc: char* = anc if c_anc is None: c_anc = "?" # Probe with the sha1 actually used for the lookup, falling back to the receiver class's # own registered sha1 when the caller passed none (so the dump is informative everywhere). - probe_sha: str = sha1 + probe_sha: char* = sha1 if probe_sha is None and anc is not None: probe_sha = self.Gen.StructGen.get_struct_sha1(anc) if probe_sha is None and cls is not None: probe_sha = self.Gen.StructGen.get_struct_sha1(cls) - c_sha: str = probe_sha + c_sha: char* = probe_sha if c_sha is None: c_sha = "?" - c_st_sha: str = "?" + c_st_sha: char* = "?" if cls is not None: - st_sha_d: str = self.Gen.StructGen.get_struct_sha1(cls) + st_sha_d: char* = self.Gen.StructGen.get_struct_sha1(cls) if st_sha_d is not None: c_st_sha = st_sha_d c_tll: int = 0 - c_vpi: str = "-" - c_tail_ty: str = "-" - c_annot_res: str = "-" + c_vpi: char* = "-" + c_tail_ty: char* = "-" + c_annot_res: char* = "-" if probe_sha is not None: c_tll = self._dep_text_ll_exists(None, probe_sha) if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(probe_sha, self.Gen.CallGenBase.TempDir) - annot_d: str = VpiReader._lookup_vpi_ret_annot(probe_sha, cls, method_name) + annot_d: char* = VpiReader._lookup_vpi_ret_annot(probe_sha, cls, method_name) if annot_d is not None: c_vpi = annot_d # Probe the string resolver here (caller's pool when available, same annotation) @@ -1363,12 +1363,12 @@ novirtual class CallGenBase: # Annotate the tail class of the raw annotation: "missing" = the class was never # registered (upstream bug); "struct"/"enum" = registered but the string resolver # still failed (resolver bug). Distinguishes the two without guessing. - dot_d: str = string.strrchr(annot_d, '.') + dot_d: char* = string.strrchr(annot_d, '.') if dot_d is not None: tail_len_d: sizet = string.strlen(dot_d + 1) tb_d: bytes = stdlib.malloc(tail_len_d + 1) if tb_d is not None: - rb_d: str = string.strchr(dot_d + 1, ']') + rb_d: char* = string.strchr(dot_d + 1, ']') if rb_d is not None: tail_len_d = sizet(uint64(rb_d) - uint64(dot_d + 1)) string.strncpy(tb_d, dot_d + 1, tail_len_d) tb_d[tail_len_d] = '\0' @@ -1379,11 +1379,11 @@ novirtual class CallGenBase: # Same-named struct entries: find_struct returns the FIRST exact match, so an earlier bogus # registration (alias/forward/stale, different ModuleSha1) silently shadows the real one. dup_n_d: int = 0 - dup_last_d: str = "-" + dup_last_d: char* = "-" # The entry's LLVM type name embeds "{sha1}.{Class}", i.e. the sha1 used when the entry # was first created (registration / forward-declare / stub injection) -- it reveals # provenance even if a later path overwrote ModuleSha1. - dup_ty_nm_d: str = "-" + dup_ty_nm_d: char* = "-" sc_n_d: int = self.Gen.StructGen.get_struct_count() sc_i_d: int = 0 while sc_i_d < sc_n_d: @@ -1393,15 +1393,15 @@ novirtual class CallGenBase: dup_n_d += 1 if e_d.ModuleSha1 is not None: dup_last_d = e_d.ModuleSha1 if e_d.Ty is not None: - nm_d: str = mlirlite.get_struct_name(e_d.Ty) + nm_d: char* = mlirlite.get_struct_name(e_d.Ty) if nm_d is not None: dup_ty_nm_d = nm_d sc_i_d += 1 # Current-file / defining-module sha1 at the moment of failure: distinguishes # "wrong sha1 captured during (vpi injection) forward-declare" from "correct sha1 # overwritten later". - cur_file_d: str = self.Gen.StructGen.get_file_module_sha1() + cur_file_d: char* = self.Gen.StructGen.get_file_module_sha1() if cur_file_d is None: cur_file_d = "-" - cur_def_d: str = self.Gen.StructGen.CurDefModuleSha1 + cur_def_d: char* = self.Gen.StructGen.CurDefModuleSha1 if cur_def_d is None: cur_def_d = "-" VLogger.error(f"method return type cannot be obtained precisely (function/text.ll/vpi stub all missed): {method_name} | [diag] cls={c_cls} struct_sha1={c_st_sha} lookup_anc={c_anc} lookup_sha1={c_sha} text_ll={c_tll} vpi_annot={c_vpi} tail_ty={c_tail_ty} annot_res={c_annot_res} same_name_entries={dup_n_d} last_same_sha1={dup_last_d} entry_ty={dup_ty_nm_d} cur_file_sha1={cur_file_d} cur_def_sha1={cur_def_d}", "HandlesExprCall") self.Gen.TypeGenErr.fatal_error(node, f"method return type cannot be obtained precisely; defaulting to i32 would truncate pointers/i64: {method_name}", "TypeError") @@ -1410,7 +1410,7 @@ novirtual class CallGenBase: # SetTempDir: set the temp dir path (called before Phase A to read dependency text.ll) # ============================================================ - def SetTempDir(self, temp_dir: str) -> None: + def SetTempDir(self, temp_dir: char*) -> None: """Set the temp directory path (single source of truth in Gen.CallGenBase)""" if self.Gen is None: return self.Gen.CallGenBase.TempDir = temp_dir @@ -1690,7 +1690,7 @@ novirtual class CallGenBase: return None # _LookupCachedRetTyText: lookup the persistent "dependency text.ll return type" cache - def _LookupCachedRetTyText(self, class_sha1: str, class_name: str, method_name: str, use_bare: int) -> str: + def _LookupCachedRetTyText(self, class_sha1: char*, class_name: char*, method_name: char*, use_bare: int) -> str: """Look up the return-type text cache: return the text on a hit, None on a miss""" if self.Gen is None or class_sha1 is None or method_name is None: return None ht: hashtable.HashTable* = self.Gen.CallGenBase.MethodRetTyMap @@ -1713,7 +1713,7 @@ novirtual class CallGenBase: return rawptr(v) # _CacheModuleRetTyTexts: one pass to register all define lines and find the first match - def _CacheModuleRetTyTexts(self, class_sha1: str, text_buf: bytes, text_len: sizet, pool: memhub.MemBuddy*, search_buf: str, search_str_len: sizet) -> mlirlite.LLVMType*: + def _CacheModuleRetTyTexts(self, class_sha1: char*, text_buf: bytes, text_len: sizet, pool: memhub.MemBuddy*, search_buf: char*, search_str_len: sizet) -> mlirlite.LLVMType*: """Single-pass register and lookup over all text.ll define lines (lookup only if table allocation fails)""" if text_buf is None or text_len == 0: return None # Merge the former two passes (register all, then scan again) into one @@ -1819,8 +1819,8 @@ novirtual class CallGenBase: rt_len = 5 # '#' + "none" else: rt_len = 1 + (ret_e - ret_s) else: rt_len = at_pos - (ls + 7) - kcopy: str = perm.alloc(name_len + 1) - tcopy: str = perm.alloc(rt_len + 1) + kcopy: char* = perm.alloc(name_len + 1) + tcopy: char* = perm.alloc(rt_len + 1) if kcopy is not None and tcopy is not None: string.strncpy(kcopy, text_buf + name_start, name_len) kcopy[name_len] = '\0' @@ -1849,7 +1849,7 @@ novirtual class CallGenBase: # _LookupMethodRetTyFromTextLL: read {temp_dir}/{sha1[0:2]}/{sha1}.text.ll and find the define line # ============================================================ - def _LookupMethodRetTyFromTextLL(self, pool: memhub.MemBuddy*, class_sha1: str, class_name: str, method_name: str, use_bare: int = 0) -> mlirlite.LLVMType*: + def _LookupMethodRetTyFromTextLL(self, pool: memhub.MemBuddy*, class_sha1: char*, class_name: char*, method_name: char*, use_bare: int = 0) -> mlirlite.LLVMType*: """Look up a method return type in a dependency module's text.ll; use_bare=1 searches a module-level "{sha1}.{method_name}" define.""" if pool is None or class_sha1 is None or method_name is None: return None if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0: return None @@ -1858,7 +1858,7 @@ novirtual class CallGenBase: if sha1_len < 2: return None # cache hit: O(1) text retrieval, rebuilt with the caller pool; miss falls through - cached_text: str = self._LookupCachedRetTyText(class_sha1, class_name, method_name, use_bare) + cached_text: char* = self._LookupCachedRetTyText(class_sha1, class_name, method_name, use_bare) if cached_text is not None: # '#' prefix = MLIR type text (form marker written by _CacheModuleRetTyTexts) if cached_text[0] == '#': return self._ParseMlirRetTyStr(pool, cached_text, 1, string.strlen(cached_text)) @@ -1931,7 +1931,7 @@ novirtual class CallGenBase: # _dep_text_ll_exists: probe whether {temp_dir}/{sha1[0:2]}/{sha1}.text.ll exists # ============================================================ - def _dep_text_ll_exists(self, pool: memhub.MemBuddy*, sha1: str) -> int: + def _dep_text_ll_exists(self, pool: memhub.MemBuddy*, sha1: char*) -> int: """Probe whether {temp_dir}/{sha1[0:2]}/{sha1}.text.ll exists, 1=yes""" if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0 or sha1 is None: return 0 sha1_len: sizet = string.strlen(sha1) diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 37afcbc..bf98650 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -37,7 +37,7 @@ define LLVMIR_TEMPLATE_BUF = 4096 novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): """Translate c.* builtins, inline asm and raw LLVM IR.""" - def _asm_append_cstr(self, dst: str, dst_size: sizet, src: str, what: str = "inline asm"): + def _asm_append_cstr(self, dst: char*, dst_size: sizet, src: char*, what: char* = "inline asm"): """Append the C string src to the end of dst; fail-fast when it does not fit. Silent truncation corrupts the generated text (a template cut in the middle of an @@ -58,12 +58,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): dst[dlen + i] = '\0' - def _asm_mangle_global_symbols(self, pool: memhub.MemBuddy*, asm_text: str, asm_size: sizet, mod: mlirlite.LLVMModule*) -> str: + def _asm_mangle_global_symbols(self, pool: memhub.MemBuddy*, asm_text: char*, asm_size: sizet, mod: mlirlite.LLVMModule*) -> str: """Fail-fast when inline asm references a SHA1-mangled module global by bare name.""" if asm_text is None or mod is None: return asm_text src_len: sizet = string.strlen(asm_text) if src_len == 0: return asm_text - out: str = pool.alloc(asm_size * 2) + out: char* = pool.alloc(asm_size * 2) if out is None: return asm_text out[0] = '\0' out_pos: sizet = 0 @@ -72,10 +72,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): matched: int = 0 cur: mlirlite.GlobalVariable* = mod.GlobalHead while cur is not None: - gname: str = cur.Name + gname: char* = cur.Name if gname is not None and string.strchr(gname, 46) is not None: - dot_g: str = string.strchr(gname, 46) - bare_g: str = dot_g + 1 + dot_g: char* = string.strchr(gname, 46) + bare_g: char* = dot_g + 1 bare_len: sizet = string.strlen(bare_g) if bare_len > 0 and i + bare_len <= src_len: if string.strncmp(asm_text + i, bare_g, bare_len) == 0: @@ -108,11 +108,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return out - def _asm_escape_for_ir(self, pool: memhub.MemBuddy*, src: str) -> str: + def _asm_escape_for_ir(self, pool: memhub.MemBuddy*, src: char*) -> str: """Escape asm text for an LLVM IR string literal.""" if src is None: return None slen: sizet = string.strlen(src) - buf: str = pool.alloc(slen * 4 + 8) + buf: char* = pool.alloc(slen * 4 + 8) if buf is None: return None pos: sizet = 0 for ch in src: @@ -144,7 +144,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return buf - def _resolve_register(self, attr_name: str) -> str: + def _resolve_register(self, attr_name: char*) -> str: """Map an ASM_DESCR attribute name to its constraint string.""" if attr_name is None: return "" @@ -248,11 +248,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) if bop.op == ast.OpKind.BitOr: - left_str: str = self._resolve_asm_descr(pool, bop.left) - right_str: str = self._resolve_asm_descr(pool, bop.right) + left_str: char* = self._resolve_asm_descr(pool, bop.left) + right_str: char* = self._resolve_asm_descr(pool, bop.right) llen: sizet = string.strlen(left_str) rlen: sizet = string.strlen(right_str) - buf: str = pool.alloc(llen + rlen + 1) + buf: char* = pool.alloc(llen + rlen + 1) if buf is None: return "" string.strcpy(buf, left_str) for i in range(int(rlen)): buf[llen + i] = right_str[i] @@ -274,11 +274,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if k == ast.ASTKind.Name: nm_b: ast.Name* = ast.Name*(node) if nm_b.id is not None: - rs_b: str = self._resolve_register(nm_b.id) + rs_b: char* = self._resolve_register(nm_b.id) if rs_b is not None and rs_b[0] != '\0': return rs_b return "" - # Constant: string constant + # Constant: char*ing constant if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) if cn.const_kind == ast.CONST_STR: return cn.str_val @@ -308,10 +308,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return None - def _asm_name_is_mangled(self, name: str) -> int: + def _asm_name_is_mangled(self, name: char*) -> int: """Return 1 when the LLVM name carries a SHA1-mangled prefix.""" if name is None: return 0 - n: str = name + n: char* = name nlen: sizet = string.strlen(n) # Strip the '@"..."' wrapper (reference name) if nlen >= 3 and n[0] == '@' and n[1] == '"' and n[nlen - 1] == '"': n = n + 2 @@ -320,7 +320,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return 0 - def _asm_add_operand(self, operands: GenTypes.AsmOperand*, count: int, val: mlirlite.Value*, constraint: str, is_output: int) -> int: + def _asm_add_operand(self, operands: GenTypes.AsmOperand*, count: int, val: mlirlite.Value*, constraint: char*, is_output: int) -> int: """Append an operand, dedup by value and direction, and return the new count.""" # fail-fast: the operand array is fixed at ASM_MAX_OPERANDS slots; dropping the # excess operand here would silently change the generated constraint/argument lists. @@ -367,7 +367,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): string.memset(clobbers, 0, 8 * ASM_MAX_CLOBBERS) # Allocate the asm text buffer - asm_text: str = pool.alloc(ASM_TEXT_BUF_SIZE) + asm_text: char* = pool.alloc(ASM_TEXT_BUF_SIZE) if asm_text is None: return None asm_text[0] = '\0' @@ -409,7 +409,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): fexpr: ast.AST* = fv.value if fexpr is None or fexpr.kind() != ast.ASTKind.Call: continue fcall: ast.Call* = ast.Call*(fexpr) - attr_nm: str = self._asm_is_c_call(fcall) + attr_nm: char* = self._asm_is_c_call(fcall) if attr_nm is None: continue is_out: int = 0 @@ -421,7 +421,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if fargs is None or len(fargs) < 1: continue val_node: ast.AST* = fargs.get(0) - cons_str: str = "" + cons_str: char* = "" if len(fargs) >= 2: cons_str = self._resolve_asm_descr(pool, fargs.get(1)) if is_out != 0: @@ -501,12 +501,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): oelt: ast.AST* = out_elts.get(oi) if oelt is None or oelt.kind() != ast.ASTKind.Call: continue ocall: ast.Call* = ast.Call*(oelt) - oattr: str = self._asm_is_c_call(ocall) + oattr: char* = self._asm_is_c_call(ocall) if oattr is None or string.strcmp(oattr, "AsmOut") != 0: continue oargs: list[ast.AST*]* = ocall.args if oargs is None or len(oargs) < 1: continue oval_node: ast.AST* = oargs.get(0) - ocons: str = "" + ocons: char* = "" if len(oargs) >= 2: ocons = self._resolve_asm_descr(pool, oargs.get(1)) if oval_node is None or oval_node.kind() != ast.ASTKind.Name: continue onm: ast.Name* = ast.Name*(oval_node) @@ -530,12 +530,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): ielt: ast.AST* = in_elts.get(ii) if ielt is None or ielt.kind() != ast.ASTKind.Call: continue icall: ast.Call* = ast.Call*(ielt) - iattr: str = self._asm_is_c_call(icall) + iattr: char* = self._asm_is_c_call(icall) if iattr is None or string.strcmp(iattr, "AsmInp") != 0: continue iargs: list[ast.AST*]* = icall.args if iargs is None or len(iargs) < 1: continue ival_node: ast.AST* = iargs.get(0) - icons: str = "" + icons: char* = "" if len(iargs) >= 2: icons = self._resolve_asm_descr(pool, iargs.get(1)) ival2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ival_node, None, 0, trans) if ival2 is None: continue @@ -551,7 +551,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for ci in range(int(clen)): celt: ast.AST* = cl_elts.get(ci) if celt is None: continue - cstr: str = self._resolve_asm_descr(pool, celt) + cstr: char* = self._resolve_asm_descr(pool, celt) if cstr is None or cstr[0] == '\0': continue # fail-fast: the clobber slot array is fixed at ASM_MAX_CLOBBERS; # dropping the excess would silently weaken the clobber list. @@ -559,7 +559,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(celt, f"inline asm has more than {ASM_MAX_CLOBBERS} clobbers (compiler limit); remove duplicates or split the asm block", "TypeError") return None cl_addr: uint64 = uint64(clobbers) + clobber_count * 8 - cl_ptr: str* = (str*)(cl_addr) + cl_ptr: char** = (str*)(cl_addr) cl_ptr[0] = cstr clobber_count += 1 @@ -574,13 +574,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for pi in range(int(plen)): pelt: ast.AST* = pos_elts.get(pi) if pelt is None: continue - pstr: str = self._resolve_asm_descr(pool, pelt) + pstr: char* = self._resolve_asm_descr(pool, pelt) if pstr is None or pstr[0] == '\0': continue if clobber_count >= ASM_MAX_CLOBBERS: self.Gen.TypeGenErr.fatal_error(pelt, f"inline asm has more than {ASM_MAX_CLOBBERS} clobbers (compiler limit); remove duplicates or split the asm block", "TypeError") return None pcl_addr: uint64 = uint64(clobbers) + clobber_count * 8 - pcl_ptr: str* = (str*)(pcl_addr) + pcl_ptr: char** = (str*)(pcl_addr) pcl_ptr[0] = pstr clobber_count += 1 @@ -700,7 +700,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if fv_fi < fv_count: orig_idx2: int = fv_orig_indices[fv_fi] new_idx2: int = orig_to_new[orig_idx2] - ph_buf2: str = pool.alloc(16) + ph_buf2: char* = pool.alloc(16) if ph_buf2 is not None: viperlib.snprintf(ph_buf2, 16, "$%d", new_idx2) self._asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, ph_buf2) @@ -714,7 +714,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # ~300 bytes, so the old fixed 512-byte cap could silently cut it. Overflow of this # (or any asm text buffer) is fail-fast in _asm_append_cstr. const_cap: sizet = ASM_CONST_BUF_SIZE + sizet(operand_count + clobber_count + 1) * 64 - const_buf: str = pool.alloc(const_cap) + const_buf: char* = pool.alloc(const_cap) if const_buf is None: return None const_buf[0] = '\0' @@ -722,7 +722,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for ci2 in range(int(operand_count)): orig_i: int = new_order[ci2] cop: GenTypes.AsmOperand* = self._asm_get_operand(operands, orig_i) - cons_val: str = cop.Constraint + cons_val: char* = cop.Constraint if cons_val is None: cons_val = "r" if first_const == 0: self._asm_append_cstr(const_buf, const_cap, ",") @@ -737,7 +737,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # Append clobber constraints ~{name} for cidx in range(int(clobber_count)): cl_addr2: uint64 = uint64(clobbers) + cidx * 8 - cname: str = (str*)(cl_addr2)[0] + cname: char* = (str*)(cl_addr2)[0] if cname is None or cname[0] == '\0': continue if first_const == 0: self._asm_append_cstr(const_buf, const_cap, ",") first_const = 0 @@ -750,7 +750,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # buffer from that worst case instead of underestimating it (544 bytes/operand # silently cut wide inlined named structs). asm_arg_cap: sizet = sizet(operand_count + 1) * 4224 + 64 - args_buf: str = pool.alloc(asm_arg_cap) + args_buf: char* = pool.alloc(asm_arg_cap) if args_buf is None: return None args_buf[0] = '\0' @@ -766,7 +766,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): first_arg = 0 # Type text - ty_buf: str = pool.alloc_tagged(4096, memhub.DETSITE_CALLGENCBUILTIN_1150) + ty_buf: char* = pool.alloc_tagged(4096, memhub.DETSITE_CALLGENCBUILTIN_1150) if ty_buf is not None: ty_buf[0] = '\0' mlirlite.TypePrint(ty_buf, 4096, aval.Ty, pool) @@ -776,15 +776,15 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 7. Escape the asm text. First replace bare symbols with mangled names # (lea rax, [rip + gdt] -> [rip + 054f5e56cbefcaa4.gdt]). - mangled_asm: str = self._asm_mangle_global_symbols(pool, asm_text, ASM_TEXT_BUF_SIZE, mod) + mangled_asm: char* = self._asm_mangle_global_symbols(pool, asm_text, ASM_TEXT_BUF_SIZE, mod) if mangled_asm is None: mangled_asm = asm_text - escaped_asm: str = self._asm_escape_for_ir(pool, mangled_asm) + escaped_asm: char* = self._asm_escape_for_ir(pool, mangled_asm) if escaped_asm is None: return None # 8. Generate and emit the IR line # The line buffer is sized after ret_ty_buf is ready (see line_cap below) - ssa_name: str = None + ssa_name: char* = None if is_void == 0: ssa_name = pool.alloc(16) if ssa_name is not None: @@ -792,7 +792,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): builder.Counter += 1 # Get the return type text - ret_ty_buf: str = pool.alloc_tagged(4096, memhub.DETSITE_CALLGENCBUILTIN_1176) + ret_ty_buf: char* = pool.alloc_tagged(4096, memhub.DETSITE_CALLGENCBUILTIN_1176) if ret_ty_buf is not None: ret_ty_buf[0] = '\0' mlirlite.TypePrint(ret_ty_buf, 4096, ret_ty, pool) @@ -801,7 +801,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): line_cap: sizet = 512 + string.strlen(escaped_asm) + string.strlen(args_buf) if const_buf is not None: line_cap += string.strlen(const_buf) if ret_ty_buf is not None: line_cap += string.strlen(ret_ty_buf) - line: str = pool.alloc(line_cap) + line: char* = pool.alloc(line_cap) if line is None: return None if is_void == 1: @@ -823,13 +823,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if output_count > 1: # Multi-output: extractvalue index out_emit_idx, then store if oo.Value is not None and oo.Value.Ty is not None and oo.Value.Ty.Pointee != 0: - ev_name: str = pool.alloc(32) + ev_name: char* = pool.alloc(32) # Size the line from its actual parts: ret_ty_buf alone can be ~4096 # bytes, so the old fixed cap could cut the instruction in half. ev_cap: sizet = ASM_LINE_BUF_SIZE + 64 if ret_ty_buf is not None: ev_cap += string.strlen(ret_ty_buf) if ssa_name is not None: ev_cap += string.strlen(ssa_name) - ev_line: str = pool.alloc(ev_cap) + ev_line: char* = pool.alloc(ev_cap) if ev_name is not None and ev_line is not None: # ssa_name is "%N"; build a unique "%asm.N.e{i}" (letter- # initial) so %N.e{i} is not parsed as id plus a bad suffix. @@ -870,7 +870,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): elif tk == ast.ASTKind.Constant: cn_only: ast.Constant* = ast.Constant*(first_arg) if cn_only.str_val is not None: cap += string.strlen(cn_only.str_val) - text: str = pool.alloc(cap) + text: char* = pool.alloc(cap) if text is None: return None text[0] = '\0' @@ -894,7 +894,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if fexpr is None: continue if fexpr.kind() == ast.ASTKind.Call: fcall: ast.Call* = ast.Call*(fexpr) - attr_nm: str = self._asm_is_c_call(fcall) + attr_nm: char* = self._asm_is_c_call(fcall) if attr_nm is not None: fargs: list[ast.AST*]* = fcall.args if fargs is None or len(fargs) < 1: continue @@ -909,7 +909,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(fcall, f"raw IR has more than {LLVMIR_MAX_OPS} input operands (compiler limit); split the block", "TypeError") return None in_vals[counts[0]] = sizet(inp_val) - pname: str = pool.alloc(32) + pname: char* = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%in%d", counts[0]) self._asm_append_cstr(text, cap, pname, "raw IR") @@ -931,7 +931,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(fcall, f"raw IR has more than {LLVMIR_MAX_OPS} output operands (compiler limit); split the block", "TypeError") return None out_vals[counts[1]] = sizet(alloca) - rname: str = pool.alloc(32) + rname: char* = pool.alloc(32) if rname is not None: viperlib.snprintf(rname, 32, "%%vpc_out%d", counts[1]) self._asm_append_cstr(text, cap, rname, "raw IR") @@ -948,7 +948,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return text - def _raw_ir_emit_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, name: str, in_vals: sizet*, in_count: int, out_vals: sizet*, out_count: int) -> mlirlite.Value*: + def _raw_ir_emit_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, name: char*, in_vals: sizet*, in_count: int, out_vals: sizet*, out_count: int) -> mlirlite.Value*: """Emit the call to the generated raw function (inputs, then output pointers).""" total: int = in_count + out_count head: mlirlite.Value* = None @@ -965,14 +965,14 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): void_ty: mlirlite.LLVMType* = mlirlite.Void(pool) return mlirlite.build_call(builder, name, head, total, void_ty, 0) - def _raw_ir_func_name(self, pool: memhub.MemBuddy*, trans: HT.Translator*, tag: str) -> str: + def _raw_ir_func_name(self, pool: memhub.MemBuddy*, trans: HT.Translator*, tag: char*) -> str: """Unique symbol name for one generated raw function.""" seq: int = self.Gen.CallGenBase.LLVMIRRegSeq + 1 self.Gen.CallGenBase.LLVMIRRegSeq = seq - sha1: str = trans.ModuleSha1 + sha1: char* = trans.ModuleSha1 if sha1 is None: sha1 = "vpc" cap: sizet = string.strlen(sha1) + string.strlen(tag) + 48 - name: str = pool.alloc(cap) + name: char* = pool.alloc(cap) if name is None: return None viperlib.snprintf(name, cap, "%s.%s_%d", sha1, tag, seq) return name @@ -994,19 +994,19 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): counts[0] = 0 counts[1] = 0 - body: str = self._raw_ir_template(pool, builder, mod, cl, trans, in_vals, out_vals, counts) + body: char* = self._raw_ir_template(pool, builder, mod, cl, trans, in_vals, out_vals, counts) if body is None: return None in_count: int = counts[0] out_count: int = counts[1] - name: str = self._raw_ir_func_name(pool, trans, "__vpc_llvmir") + name: char* = self._raw_ir_func_name(pool, trans, "__vpc_llvmir") if name is None: return None # Sidecar definition: linkonce_odr + alwaysinline so llvm-link merges it with the # declaration and opt -passes=always-inline restores inline semantics. cap: sizet = string.strlen(body) + 256 + sizet(in_count + out_count) * 4352 - fn_buf: str = pool.alloc(cap) - ty_buf: str = pool.alloc(4096) + fn_buf: char* = pool.alloc(cap) + ty_buf: char* = pool.alloc(4096) if fn_buf is None or ty_buf is None: return None fn_buf[0] = '\0' viperlib.snprintf(fn_buf, cap, "define linkonce_odr void @\"%s\"(", name) @@ -1082,17 +1082,17 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): counts[0] = 0 counts[1] = 0 - body: str = self._raw_ir_template(pool, builder, mod, cl, trans, in_vals, out_vals, counts) + body: char* = self._raw_ir_template(pool, builder, mod, cl, trans, in_vals, out_vals, counts) if body is None: return None in_count: int = counts[0] out_count: int = counts[1] - name: str = self._raw_ir_func_name(pool, trans, "__vpc_mlir") + name: char* = self._raw_ir_func_name(pool, trans, "__vpc_mlir") if name is None: return None fn: mlirlite.Function* = mlirlite.create_function(pool, mod, name, mlirlite.Void(pool)) if fn is None: return None - pn: str = pool.alloc(32) + pn: char* = pool.alloc(32) for k in range(in_count): v: mlirlite.Value* = mlirlite.Value*(in_vals[k]) if v is None or v.Ty is None: return None @@ -1108,9 +1108,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): fn.Attrs = "alwaysinline" cap: sizet = string.strlen(body) + 128 + sizet(out_count) * 8448 - raw: str = pool.alloc(cap) - ty_buf: str = pool.alloc(4096) - ptr_buf: str = pool.alloc(4096) + raw: char* = pool.alloc(cap) + ty_buf: char* = pool.alloc(4096) + ptr_buf: char* = pool.alloc(4096) if raw is None or ty_buf is None or ptr_buf is None: return None string.strcpy(raw, body) pos: sizet = string.strlen(raw) diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 7efcb75..d93081a 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -20,7 +20,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # (GEP vtable ptr -> load method slot -> bitcast -> call). # ============================================================ - def _do_virtual_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: str, method_name: str, self_ptr: mlirlite.Value*, args_head: mlirlite.Value*, args_count: int, found_func: mlirlite.Function*, ret_ty: mlirlite.LLVMType*, vtable_base: mlirlite.Value* = None) -> mlirlite.Value*: + def _do_virtual_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: char*, method_name: char*, self_ptr: mlirlite.Value*, args_head: mlirlite.Value*, args_count: int, found_func: mlirlite.Function*, ret_ty: mlirlite.LLVMType*, vtable_base: mlirlite.Value* = None) -> mlirlite.Value*: """Call a virtual method indirectly through the vtable; returns None for void.""" if pool is None or builder is None or class_name is None or method_name is None: return None if self_ptr is None or args_head is None: return None @@ -55,7 +55,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): for mi in range(int(vc_entry.VTableMethodCount)): mname_addr: sizet = methods_arr[mi] if mname_addr == 0: continue - mname: str = rawptr(mname_addr) + mname: char* = rawptr(mname_addr) if mname is not None and string.strcmp(mname, method_name) == 0: method_index = mi break @@ -146,7 +146,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # first argument (goes through virtual dispatch if the method is in the vtable). # ============================================================ - def _call_method_on_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: str, method_name: str, self_ptr: mlirlite.Value*, extra_args: sizet*, extra_count: int, trans: HT.Translator*, node: ast.AST* = None, is_volatile: int = 0, arg_nodes: list[ast.AST*]* = None, recv_life: int = -1) -> mlirlite.Value*: + def _call_method_on_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: char*, method_name: char*, self_ptr: mlirlite.Value*, extra_args: sizet*, extra_count: int, trans: HT.Translator*, node: ast.AST* = None, is_volatile: int = 0, arg_nodes: list[ast.AST*]* = None, recv_life: int = -1) -> mlirlite.Value*: """Call a method on a struct pointer; adds a volatile barrier for constructors.""" if pool is None or builder is None or class_name is None or method_name is None: return None if self_ptr is None: return None @@ -157,7 +157,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # `__new__` 不查:其形参与 __init__ 共享且可能被裁剪,位置对应不可靠。 if arg_nodes is not None and string.strcmp(method_name, "__init__") == 0: esc_mask_ci: int = GenApi.get_param_escapes_method(pool, class_name, method_name) - sha_ci: str = None + sha_ci: char* = None if esc_mask_ci == 0: # 跨模块回退(v3):构造器常定义在别的模块(self.f = p 写在那边) sha_ci = self.Gen.StructGen.get_struct_sha1(class_name) @@ -201,7 +201,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cmop_struct_ty is None and cmop_entry is not None: cmop_struct_ty = cmop_entry.Ty # Build the lookup name: ClassName.method_name. - lookup_name: str = pool.alloc(128) + lookup_name: char* = pool.alloc(128) if lookup_name is None: return None viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name) @@ -214,13 +214,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if arg_nodes is not None: m_argc2 = len(arg_nodes) ovl_m2: mlirlite.Function* = self.Gen.CallGenLeafKit.resolve_overload_call(pool, trans, trans._funcs, trans._func_count, lookup_name, trans.ModuleSha1, arg_nodes, m_argc2, node, 1, 1) if ovl_m2 is None: return None - fn_sym2: str = mlirlite.function_get_name(ovl_m2) + fn_sym2: char* = mlirlite.function_get_name(ovl_m2) if fn_sym2 is not None: pre_len2: sizet = 17 + string.strlen(lookup_name) if string.strlen(fn_sym2) > pre_len2: - sfx2: str = fn_sym2 + pre_len2 + sfx2: char* = fn_sym2 + pre_len2 short_cap2: sizet = string.strlen(method_name) + string.strlen(sfx2) + 1 - short_buf2: str = pool.alloc(short_cap2) + short_buf2: char* = pool.alloc(short_cap2) if short_buf2 is not None: viperlib.snprintf(short_buf2, short_cap2, "%s%s", method_name, sfx2) method_name = short_buf2 @@ -229,14 +229,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if m_ovl_done2 == 0: found_func = self.find_func_in_module(mod, lookup_name) # Determine the call name. - call_name: str = lookup_name + call_name: char* = lookup_name if found_func is not None: - found_name: str = mlirlite.function_get_name(found_func) + found_name: char* = mlirlite.function_get_name(found_func) if found_name is not None: call_name = found_name else: # found_func is None (stub not injected): build the call name from the # class module SHA1, preferring the entry's SHA1. - cls_sha1: str = None + cls_sha1: char* = None if cmop_entry is not None: cls_sha1 = cmop_entry.ModuleSha1 else: cls_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if cls_sha1 is None and trans is not None: @@ -245,15 +245,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cls_sha1 is None: # [D6 truncation] Allocate by exact length instead of a fixed 256 # buffer so long class/method names are not silently truncated. - msg_fmt: str = "Class '%s' method '%s': module SHA1 not found" + msg_fmt: char* = "Class '%s' method '%s': module SHA1 not found" msg_size: sizet = string.strlen(msg_fmt) + string.strlen(class_name) + string.strlen(method_name) - 4 + 1 - err_msg: str = pool.alloc(msg_size) + err_msg: char* = pool.alloc(msg_size) if err_msg is not None: viperlib.snprintf(err_msg, msg_size, msg_fmt, class_name, method_name) self.Gen.TypeGenErr.fatal_error(node, err_msg) self.Gen.TypeGenErr.fatal_error(node, "Module SHA1 not found") # Build the call name: {cls_sha1}.{lookup_name}. - mangled2: str = pool.alloc(string.strlen(cls_sha1) + string.strlen(lookup_name) + 2) + mangled2: char* = pool.alloc(string.strlen(cls_sha1) + string.strlen(lookup_name) + 2) if mangled2 is not None: viperlib.snprintf(mangled2, string.strlen(cls_sha1) + string.strlen(lookup_name) + 2, "%s.%s", cls_sha1, lookup_name) call_name = mangled2 @@ -267,9 +267,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): elif string.strcmp(method_name, "__getitem__") == 0 or string.strcmp(method_name, "__new__") == 0: # fail-fast: __getitem__/__new__ must return a pointer; a missing # return type means a broken stub declare (silent ptr truncation). - msg_fmt1: str = "Cannot determine return type of method '%s' (stub declare return type missing)" + msg_fmt1: char* = "Cannot determine return type of method '%s' (stub declare return type missing)" msg_size1: sizet = string.strlen(msg_fmt1) + string.strlen(method_name) - 2 + 1 - err_cm1: str = pool.alloc(msg_size1) + err_cm1: char* = pool.alloc(msg_size1) if err_cm1 is not None: viperlib.snprintf(err_cm1, msg_size1, msg_fmt1, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm1) @@ -284,18 +284,18 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cmop_struct_ty is not None: call_ret_ty = mlirlite.Ptr(pool, cmop_struct_ty) else: # [D6 truncation] Use exact length instead of a fixed 256 buffer. - msg_fmt2: str = "Unknown self struct type of method '%s' (field type degraded, dependency module not preregistered?)" + msg_fmt2: char* = "Unknown self struct type of method '%s' (field type degraded, dependency module not preregistered?)" msg_size2: sizet = string.strlen(msg_fmt2) + string.strlen(method_name) - 2 + 1 - err_cm2: str = pool.alloc(msg_size2) + err_cm2: char* = pool.alloc(msg_size2) if err_cm2 is not None: viperlib.snprintf(err_cm2, msg_size2, msg_fmt2, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm2) self.Gen.TypeGenErr.fatal_error(node, "Unknown self struct type") elif string.strcmp(method_name, "__getitem__") == 0: # [D6 truncation] Use exact length instead of a fixed 256 buffer. - msg_fmt3: str = "Method '%s.__getitem__': stub declare not injected (dependency module vpi missing or wrong topological order); cannot determine return type" + msg_fmt3: char* = "Method '%s.__getitem__': stub declare not injected (dependency module vpi missing or wrong topological order); cannot determine return type" msg_size3: sizet = string.strlen(msg_fmt3) + string.strlen(class_name) - 2 + 1 - err_cm3: str = pool.alloc(msg_size3) + err_cm3: char* = pool.alloc(msg_size3) if err_cm3 is not None: viperlib.snprintf(err_cm3, msg_size3, msg_fmt3, class_name) self.Gen.TypeGenErr.fatal_error(node, err_cm3) @@ -307,7 +307,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # is_local_mod exemption: when the target module is the one being # translated, take the return type from the current IR, not text.ll. if cls_sha1 is not None and trans is not None and trans.ModuleSha1 is not None and string.strncmp(cls_sha1, trans.ModuleSha1, 16) == 0: - local_lk_cm2: str = pool.alloc(string.strlen(class_name) + string.strlen(method_name) + 2) + local_lk_cm2: char* = pool.alloc(string.strlen(class_name) + string.strlen(method_name) + 2) if local_lk_cm2 is not None: viperlib.snprintf(local_lk_cm2, string.strlen(class_name) + string.strlen(method_name) + 2, "%s.%s", class_name, method_name) local_fn_cm2: mlirlite.Function* = self.find_func_in_module(mod, local_lk_cm2) @@ -331,7 +331,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # returns None and breaks expression translation). call_ret_ty = mlirlite.Int32(pool) else: - err_cm4: str = pool.alloc(256) + err_cm4: char* = pool.alloc(256) if err_cm4 is not None: viperlib.snprintf(err_cm4, 256, "Cannot determine return type of method '%s.%s' (neither text.ll nor vpi hit, cross-module stub not injected)", class_name, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm4) @@ -387,7 +387,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # depends on mdf_gd (the only holder of stdlib constant snapshots). # 必须带方法所属模块 SHA1:裸名跨模块会命中同名方法(`run`/`init`)的签名。 mdf_gd: GenTypes.FuncDefaultsEntry* = None - cmop_sha: str = self.Gen.StructGen.get_struct_sha1(class_name) + cmop_sha: char* = self.Gen.StructGen.get_struct_sha1(class_name) if cmop_sha is not None: mdf_gd = self.Gen.CallGenLeafKit.find_func_defaults(lookup_name, cmop_sha) if mdf_defaults is None and mdf_gd is not None: mdf_defaults = mdf_gd.Defaults @@ -396,9 +396,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Cross-module stub fallback: when found_func is None and the table has no # ParamCount, fill it from the vpi cache to align declare/call with define. - vpi_pa: str = None + vpi_pa: char* = None if mdf_param_count == 0 and found_func is None: - vpi_sha1_p: str = None + vpi_sha1_p: char* = None if cmop_entry is not None and cmop_entry.ModuleSha1 is not None: vpi_sha1_p = cmop_entry.ModuleSha1 else: vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) if vpi_sha1_p is not None: @@ -417,7 +417,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ppcnt_f2: int = 0 ppn_f2: mlirlite.Param* = mlirlite.function_get_param_head(found_func) while ppn_f2 is not None: - fp_nm_f2: str = mlirlite.param_get_name(ppn_f2) + fp_nm_f2: char* = mlirlite.param_get_name(ppn_f2) if fp_nm_f2 is None or (string.strcmp(fp_nm_f2, "%__eh_msg_out__") != 0 and string.strcmp(fp_nm_f2, "%__eh_code_out__") != 0): ppcnt_f2 += 1 ppn_f2 = mlirlite.param_get_next(ppn_f2) @@ -555,7 +555,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): for cmop_mi in range(int(cmop_entry.VTableMethodCount)): cmop_mname_addr: sizet = cmop_methods_arr[cmop_mi] if cmop_mname_addr == 0: continue - cmop_mname: str = rawptr(cmop_mname_addr) + cmop_mname: char* = rawptr(cmop_mname_addr) if cmop_mname is not None and string.strcmp(cmop_mname, method_name) == 0: cmop_method_idx = cmop_mi break @@ -600,14 +600,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # land on a procedure. A generic instance (Class[T]) is emitted in this module only after all # bodies, so the call site cannot read its signature; the template method is the only source. # No return annotation = procedure = void, matching the unified body pipeline. - def _predicted_generic_method_is_void(self, pool: memhub.MemBuddy*, class_name: str, method_name: str) -> int: + def _predicted_generic_method_is_void(self, pool: memhub.MemBuddy*, class_name: char*, method_name: char*) -> int: """1 when the template method (of a Class[T] instance) has no return annotation.""" if class_name is None or method_name is None: return 0 - br: str = string.strchr(class_name, '[') + br: char* = string.strchr(class_name, '[') if br is None: return 0 bare_len: sizet = sizet(uint64(br) - uint64(class_name)) if bare_len == 0: return 0 - bare: str = pool.alloc(bare_len + 1) + bare: char* = pool.alloc(bare_len + 1) if bare is None: return 0 string.strncpy(bare, class_name, bare_len) bare[bare_len] = '\0' @@ -642,7 +642,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # object pointer (obj_ptr, an alloca of Ptr(StructTy)) as the self argument. # ============================================================ - def _translate_method_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: str, method_name: str, obj_ptr: mlirlite.Value*, cl: ast.Call*, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_method_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: char*, method_name: char*, obj_ptr: mlirlite.Value*, cl: ast.Call*, trans: HT.Translator*) -> mlirlite.Value*: """Translate a method call; returns the call result Value.""" if pool is None or builder is None or class_name is None or method_name is None: return None if obj_ptr is None or cl is None: return None @@ -653,7 +653,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cargs_mc: list[ast.AST*]* = cl.args if cargs_mc is not None: esc_mask_mc: int = GenApi.get_param_escapes_method(pool, class_name, method_name) - sha_mc: str = None + sha_mc: char* = None if esc_mask_mc == 0: # 跨模块回退(v3):本文件摘要表按文件重置,跨模块只能查 .vpi 落盘的摘要 sha_mc = self.Gen.StructGen.get_struct_sha1(class_name) @@ -702,19 +702,19 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cargs_mc is not None: wf_mask_mc = GenApi.get_param_willfree_method(pool, class_name, method_name) if wf_mask_mc == 0: - sha_wf_mc: str = self.Gen.StructGen.get_struct_sha1(class_name) + sha_wf_mc: char* = self.Gen.StructGen.get_struct_sha1(class_name) wf_mask_mc = self.Gen.CallGenBase.lookup_willfree_via_vpi(pool, sha_wf_mc, class_name, method_name) # list generic container method: dispatch to _translate_list_builtin_call inline # when the method is a list builtin; use the receiver's actual struct name. - lb_src: str = class_name + lb_src: char* = class_name if lb_src is None or lb_src[0] == '\0': lb_sty_s: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(obj_ptr) if lb_sty_s is not None: - lb_nm_s: str = mlirlite.get_struct_name(lb_sty_s) + lb_nm_s: char* = mlirlite.get_struct_name(lb_sty_s) if lb_nm_s is not None: lb_src = lb_nm_s if method_name is not None and lb_src is not None: - lb_cls: str = lb_src + lb_cls: char* = lb_src # Strip the cross-module specialization sha1 prefix "{16hex}." using # the single source GenApi.sha1_prefix_len. lb_pfx_d: int = GenApi.sha1_prefix_len(lb_cls) @@ -744,7 +744,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # [D25 fail-fast] A non-builtin method call on a bare generic template base # (e.g. "list") has an unknown element type; fail fast rather than assume it. - cm_bare: str = None + cm_bare: char* = None if lb_src is not None: cm_pfx: int = GenApi.sha1_prefix_len(lb_src) cm_bare = lb_src + cm_pfx if cm_pfx != 0 else lb_src @@ -762,13 +762,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # [D25] Generic container receivers use the actual struct name (the IR-level # truth); resolve via CallGenProp._resolve_generic_receiver_name. - mc_act_d: str = self.Gen.CallGenProp._resolve_generic_receiver_name(pool, mc_struct_ty, method_name, cl) + mc_act_d: char* = self.Gen.CallGenProp._resolve_generic_receiver_name(pool, mc_struct_ty, method_name, cl) if mc_act_d is not None: class_name = mc_act_d # Build the lookup name; allocate by exact length ([D6]) since the # specialized class name can be long (e.g. list[rawptr[sha.AST]]). lk_cap: sizet = string.strlen(class_name) + string.strlen(method_name) + 2 - lookup_name: str = pool.alloc(lk_cap) + lookup_name: char* = pool.alloc(lk_cap) if lookup_name is None: return None viperlib.snprintf(lookup_name, lk_cap, "%s.%s", class_name, method_name) @@ -784,13 +784,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if m_args_o is not None: m_argc_o = len(m_args_o) ovl_m: mlirlite.Function* = self.Gen.CallGenLeafKit.resolve_overload_call(pool, trans, trans._funcs, trans._func_count, lookup_name, trans.ModuleSha1, m_args_o, m_argc_o, cl.func, 1, 1) if ovl_m is None: return None - fn_sym_o: str = mlirlite.function_get_name(ovl_m) + fn_sym_o: char* = mlirlite.function_get_name(ovl_m) if fn_sym_o is not None: pre_len_o: sizet = 17 + string.strlen(lookup_name) if string.strlen(fn_sym_o) > pre_len_o: - sfx_o: str = fn_sym_o + pre_len_o + sfx_o: char* = fn_sym_o + pre_len_o short_cap: sizet = string.strlen(method_name) + string.strlen(sfx_o) + 1 - short_buf_o: str = pool.alloc(short_cap) + short_buf_o: char* = pool.alloc(short_cap) if short_buf_o is not None: viperlib.snprintf(short_buf_o, short_cap, "%s%s", method_name, sfx_o) method_name = short_buf_o @@ -804,20 +804,20 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # ({sha1}.list[int].get), so match by suffix using mc_entry.Name. if found_func is None and mc_entry is not None and mc_entry.Name is not None: if string.strcmp(mc_entry.Name, class_name) != 0: - spec_lookup: str = pool.alloc(160) + spec_lookup: char* = pool.alloc(160) if spec_lookup is not None: viperlib.snprintf(spec_lookup, 160, "%s.%s", mc_entry.Name, method_name) found_func = self.find_func_in_module(mod, spec_lookup) # Walk the MRO ancestor chain for the parent method (first parent wins). - mc_anc: str = None # the method's defining class (for multi-inheritance this-adjust) + mc_anc: char* = None # the method's defining class (for multi-inheritance this-adjust) if found_func is None: mro_ptr: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi: int = 1 while mro_ptr is not None and mro_ptr[mi] != 0: - anc: str = rawptr(mro_ptr[mi]) + anc: char* = rawptr(mro_ptr[mi]) if anc is not None: - parent_lookup: str = pool.alloc(128) + parent_lookup: char* = pool.alloc(128) if parent_lookup is not None: viperlib.snprintf(parent_lookup, 128, "%s.%s", anc, method_name) parent_func: mlirlite.Function* = self.find_func_in_module(mod, parent_lookup) @@ -832,7 +832,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if found_func is None: sib_recv_local: int = 1 if trans is not None and trans.ModuleSha1 is not None: - sib_recv_sha1: str = None + sib_recv_sha1: char* = None if mc_entry is not None and mc_entry.ModuleSha1 is not None: sib_recv_sha1 = mc_entry.ModuleSha1 else: sib_recv_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if sib_recv_sha1 is not None: @@ -844,12 +844,12 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): while sc_i < sc_n and found_func is None: cand_entry: GenTypes.StructEntry* = self.Gen.StructGen._get_struct_entry(sc_i) if cand_entry is not None and cand_entry.Name is not None: - cand_name: str = cand_entry.Name + cand_name: char* = cand_entry.Name if string.strcmp(cand_name, class_name) != 0: # Specialized generic class name contains '[': not a Mixin candidate. if string.strchr(cand_name, '[') is None: if self._mixin_sibling_same_composite(pool, class_name, cand_name) != 0: - cand_lookup: str = pool.alloc(128) + cand_lookup: char* = pool.alloc(128) if cand_lookup is not None: viperlib.snprintf(cand_lookup, 128, "%s.%s", cand_name, method_name) cand_func: mlirlite.Function* = self.find_func_in_module(mod, cand_lookup) @@ -860,9 +860,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Determine the call name (default "ClassName.method"; when not found, build # it along the MRO using the defining class's SHA1). - call_name: str = lookup_name + call_name: char* = lookup_name if found_func is not None: - found_name: str = mlirlite.function_get_name(found_func) + found_name: char* = mlirlite.function_get_name(found_func) if found_name is not None: call_name = found_name # Determine the return type. @@ -878,8 +878,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): call_ret_ty = sp_ty2 # Special methods (e.g. __before_init__) also need the sha1 prefix on # cross-module calls, else the bare name links to an undefined symbol. - sp_anc_name: str = class_name - sp_anc_sha1: str = None + sp_anc_name: char* = class_name + sp_anc_sha1: char* = None if mc_entry is not None: sp_anc_sha1 = mc_entry.ModuleSha1 else: sp_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if sp_anc_sha1 is None and mc_struct_ty is not None: @@ -889,7 +889,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Only extract sha1 when the type name is "{16hex}.{Class}" # (via GenApi.sha1_prefix_len), avoiding false positives. if GenApi.sha1_prefix_len(type_name_sp) != 0: - sb_sp: str = pool.alloc(17) + sb_sp: char* = pool.alloc(17) if sb_sp is not None: string.strncpy(sb_sp, type_name_sp, 16) sb_sp[16] = '\0' @@ -898,15 +898,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pass if sp_anc_sha1 is not None: ml_sp: sizet = string.strlen(sp_anc_sha1) + string.strlen(sp_anc_name) + string.strlen(method_name) + 3 - mangled_sp: str = pool.alloc(ml_sp) + mangled_sp: char* = pool.alloc(ml_sp) if mangled_sp is not None: viperlib.snprintf(mangled_sp, ml_sp, "%s.%s.%s", sp_anc_sha1, sp_anc_name, method_name) call_name = mangled_sp else: # The method's defining class (source of cross-module name / return # type); defaults to class_name and updates on MRO fallback. - ret_anc_name: str = class_name - ret_anc_sha1: str = None + ret_anc_name: char* = class_name + ret_anc_sha1: char* = None if mc_entry is not None: ret_anc_sha1 = mc_entry.ModuleSha1 else: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if ret_anc_sha1 is None: @@ -914,7 +914,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mro_s0: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi_s0: int = 1 while mro_s0 is not None and mro_s0[mi_s0] != 0 and ret_anc_sha1 is None: - anc_s0: str = rawptr(mro_s0[mi_s0]) + anc_s0: char* = rawptr(mro_s0[mi_s0]) if anc_s0 is not None: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(anc_s0) mi_s0 += 1 @@ -922,15 +922,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # registered yet; trigger it (idempotent), then re-lookup. gen_done: int = 0 if class_name is not None: - lbkt_g: str = string.strchr(class_name, '[') + lbkt_g: char* = string.strchr(class_name, '[') if lbkt_g is not None: - rbkt_g: str = string.strrchr(class_name, ']') + rbkt_g: char* = string.strrchr(class_name, ']') if rbkt_g is not None and rbkt_g > lbkt_g: base_len_g: sizet = sizet(uint64(lbkt_g) - uint64(class_name)) arg_len_g: sizet = sizet(uint64(rbkt_g) - uint64(lbkt_g) - 1) if base_len_g > 0 and arg_len_g > 0: - base_buf_g: str = pool.alloc(base_len_g + 1) - arg_buf_g: str = pool.alloc(arg_len_g + 1) + base_buf_g: char* = pool.alloc(base_len_g + 1) + arg_buf_g: char* = pool.alloc(arg_len_g + 1) if base_buf_g is not None and arg_buf_g is not None: string.strncpy(base_buf_g, class_name, base_len_g) base_buf_g[base_len_g] = '\0' @@ -939,14 +939,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ta_list_g: list[str]* = list[str](pool, 8) if ta_list_g is not None: # Comma-separated multiple type args (list[X] / dict[K, V]). - cur_arg_g: str = arg_buf_g + cur_arg_g: char* = arg_buf_g while cur_arg_g is not None: - comma_g: str = string.strchr(cur_arg_g, ',') + comma_g: char* = string.strchr(cur_arg_g, ',') if comma_g is None: ta_list_g.append(cur_arg_g) break seg_len_g: sizet = sizet(uint64(comma_g) - uint64(cur_arg_g)) - seg_buf_g: str = pool.alloc(seg_len_g + 1) + seg_buf_g: char* = pool.alloc(seg_len_g + 1) if seg_buf_g is not None: string.strncpy(seg_buf_g, cur_arg_g, seg_len_g) seg_buf_g[seg_len_g] = '\0' @@ -954,16 +954,16 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cur_arg_g = comma_g + 1 # base_buf_g may carry a template module SHA1 prefix # ({tpl}.GSList); strip it before template lookup. - base_clean_g: str = base_buf_g + base_clean_g: char* = base_buf_g # [C10] SHA1 prefix detection uses the single source; # take the cut length from its return value. base_pfx_g: int = GenApi.sha1_prefix_len(base_buf_g) if base_pfx_g != 0: base_clean_g = base_buf_g + sizet(base_pfx_g) - spec_name_g: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_clean_g, ta_list_g) + spec_name_g: char* = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_clean_g, ta_list_g) if spec_name_g is not None: # Re-lookup the specialized function after specialization; # find_func_in_module matches both bare and tpl-prefixed names. - spec_lk_g: str = pool.alloc(string.strlen(class_name) + string.strlen(method_name) + 2) + spec_lk_g: char* = pool.alloc(string.strlen(class_name) + string.strlen(method_name) + 2) if spec_lk_g is not None: viperlib.snprintf(spec_lk_g, string.strlen(class_name) + string.strlen(method_name) + 2, "%s.%s", class_name, method_name) spec_found_g: mlirlite.Function* = self.find_func_in_module(mod, spec_lk_g) @@ -977,7 +977,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # is_local_mod exemption: when the method is defined in the module # being translated, take the return type from the current IR. if trans is not None and ret_anc_sha1 is not None and trans.ModuleSha1 is not None and string.strncmp(ret_anc_sha1, trans.ModuleSha1, 16) == 0: - local_lk_lm: str = pool.alloc(string.strlen(ret_anc_name) + string.strlen(method_name) + 2) + local_lk_lm: char* = pool.alloc(string.strlen(ret_anc_name) + string.strlen(method_name) + 2) if local_lk_lm is not None: viperlib.snprintf(local_lk_lm, string.strlen(ret_anc_name) + string.strlen(method_name) + 2, "%s.%s", ret_anc_name, method_name) local_fn_lm: mlirlite.Function* = self.find_func_in_module(mod, local_lk_lm) @@ -999,9 +999,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mro_v2: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi_v2: int = 1 while mro_v2 is not None and mro_v2[mi_v2] != 0 and vpi_ret_ty is None: - anc_v2: str = rawptr(mro_v2[mi_v2]) + anc_v2: char* = rawptr(mro_v2[mi_v2]) if anc_v2 is not None and string.strcmp(anc_v2, class_name) != 0: - anc_sha1_v2: str = self.Gen.StructGen.get_struct_sha1(anc_v2) + anc_sha1_v2: char* = self.Gen.StructGen.get_struct_sha1(anc_v2) vpi_ret_ty = self._lookup_method_ret_ty_via_vpi(pool, anc_sha1_v2, anc_v2, method_name, trans) if vpi_ret_ty is not None: ret_anc_name = anc_v2 @@ -1018,9 +1018,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mro_t2: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi_t2: int = 1 while mro_t2 is not None and mro_t2[mi_t2] != 0 and looked_up_ty is None: - anc_t2: str = rawptr(mro_t2[mi_t2]) + anc_t2: char* = rawptr(mro_t2[mi_t2]) if anc_t2 is not None and string.strcmp(anc_t2, class_name) != 0: - anc_sha1_t2: str = self.Gen.StructGen.get_struct_sha1(anc_t2) + anc_sha1_t2: char* = self.Gen.StructGen.get_struct_sha1(anc_t2) looked_up_ty = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_t2, anc_t2, method_name) if looked_up_ty is not None: ret_anc_name = anc_t2 @@ -1045,7 +1045,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Only extract sha1 when the type name is "{16hex}.{Class}" # (via the single source GenApi.sha1_prefix_len). if GenApi.sha1_prefix_len(type_name_st) != 0: - sha1_from_ty: str = pool.alloc(17) + sha1_from_ty: char* = pool.alloc(17) if sha1_from_ty is not None: string.strncpy(sha1_from_ty, type_name_st, 16) sha1_from_ty[16] = '\0' @@ -1054,7 +1054,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pass if ret_anc_name is not None and ret_anc_sha1 is not None: ml_anc: sizet = string.strlen(ret_anc_sha1) + string.strlen(ret_anc_name) + string.strlen(method_name) + 3 - mangled_anc: str = pool.alloc(ml_anc) + mangled_anc: char* = pool.alloc(ml_anc) if mangled_anc is not None: viperlib.snprintf(mangled_anc, ml_anc, "%s.%s.%s", ret_anc_sha1, ret_anc_name, method_name) call_name = mangled_anc @@ -1082,17 +1082,17 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): is_first_parent_th: int = 0 mro_fp_th: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) if mro_fp_th is not None and mro_fp_th[1] != 0: - first_parent_th: str = rawptr(mro_fp_th[1]) + first_parent_th: char* = rawptr(mro_fp_th[1]) if first_parent_th is not None and string.strcmp(first_parent_th, mc_anc) == 0: is_first_parent_th = 1 anc_entry_th: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(mc_anc) # Parent with no fields (FieldCount==0): the method body reads no layout # fields, so this needs no byte adjust; pass it through unchanged. if anc_entry_th is not None and anc_entry_th.FieldCount > 0: - anc_first_name_th: str = None + anc_first_name_th: char* = None for afi_th in range(int(anc_entry_th.FieldCount)): afe_th: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(anc_entry_th, afi_th) if afe_th is not None: - afn_th: str = self.Gen.StructGen.get_field_name_ptr(afe_th) + afn_th: char* = self.Gen.StructGen.get_field_name_ptr(afe_th) if afn_th is not None and string.strcmp(afn_th, "__vtable__") != 0: anc_first_name_th = afn_th break @@ -1174,7 +1174,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): arg_node_k: ast.AST* = None if pi_k < can: arg_node_k = cargs.get(pi_k) else: - pname_k: str = mlirlite.param_get_name(cur_param_k) + pname_k: char* = mlirlite.param_get_name(cur_param_k) if pname_k is not None: ki_k: int for ki_k in range(int(kwc)): @@ -1187,7 +1187,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if arg_node_k is not None: # Fetch the param type first (char literal -> str param needs a materialized string). pty_k0: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param_k) - ao_name_k: str = None + ao_name_k: char* = None if found_func is not None: ao_name_k = mlirlite.function_get_name(found_func) arg_val_k = self.Gen.CallGenBase.translate_call_arg(builder, pool, mod, trans, ao_name_k, pi_k, arg_node_k, pty_k0, None) if arg_val_k is None: @@ -1234,7 +1234,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pi += 1 if pp is not None: pty = mlirlite.param_get_ty(pp) # Value-reference params (&T / &temp T): auto-address (self is param 0, arg ai -> param ai+1). - ao_name_p: str = None + ao_name_p: char* = None if found_func is not None: ao_name_p = mlirlite.function_get_name(found_func) arg_val: mlirlite.Value* = self.Gen.CallGenBase.translate_call_arg(builder, pool, mod, trans, ao_name_p, int(ai) + 1, arg_node, pty, None) if arg_val is None: @@ -1275,7 +1275,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mdf_param_count: int = 0 # 方法所属模块 SHA1:后面所有 defaults 查找都必须带上它,绝不跨模块按名搜 # (`run`/`init` 这类方法名在多个模块里都有,裸名会拿错签名去补参)。 - vpi_sha1_p: str = None + vpi_sha1_p: char* = None if mc_entry is not None and mc_entry.ModuleSha1 is not None: vpi_sha1_p = mc_entry.ModuleSha1 else: vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) if trans is not None and trans._funcs is not None: @@ -1304,7 +1304,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Cross-module stub fallback: when the dependency's vpi is not loaded the # table lacks ParamCount; fill it from the vpi text cache. - vpi_pa: str = None + vpi_pa: char* = None if mdf_param_count == 0 and found_func is None: if vpi_sha1_p is not None: vpi_pa = self.Gen.CallGenBase._vpi_method_param_annot(pool, vpi_sha1_p, class_name, method_name) @@ -1322,7 +1322,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ppcnt_f: int = 0 ppn_f: mlirlite.Param* = mlirlite.function_get_param_head(found_func) while ppn_f is not None: - fp_nm_f: str = mlirlite.param_get_name(ppn_f) + fp_nm_f: char* = mlirlite.param_get_name(ppn_f) if fp_nm_f is None or (string.strcmp(fp_nm_f, "%__eh_msg_out__") != 0 and string.strcmp(fp_nm_f, "%__eh_code_out__") != 0): ppcnt_f += 1 ppn_f = mlirlite.param_get_next(ppn_f) @@ -1420,7 +1420,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): for mc_mi in range(int(mc_entry.VTableMethodCount)): mc_mname_addr: sizet = mc_methods_arr[mc_mi] if mc_mname_addr == 0: continue - mc_mname: str = rawptr(mc_mname_addr) + mc_mname: char* = rawptr(mc_mname_addr) if mc_mname is not None and string.strcmp(mc_mname, method_name) == 0: mc_method_idx = mc_mi break @@ -1447,7 +1447,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # _translate_list_builtin_call - inline translation of list builtin methods # (layout: __data__(0) __count__(8) __elem_size__(32) ...); lm_obj is Ptr(list-struct). - def _translate_list_builtin_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, lm_name: str, lm_obj: mlirlite.Value*, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_list_builtin_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, lm_name: char*, lm_obj: mlirlite.Value*, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*) -> mlirlite.Value*: """Translate a list builtin method call; returns None for void methods.""" if pool is None or builder is None or lm_obj is None or lm_name is None: return None i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) @@ -1456,7 +1456,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Element type T parsed from the list specialization name (list[int]->i32, # list[str]->i8*; unknown/pointer elements -> i8*). lm_esty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) - lm_ename: str = None + lm_ename: char* = None if lm_esty is not None: lm_ename = mlirlite.get_struct_name(lm_esty) lm_elem_ty: mlirlite.LLVMType* = None if lm_ename is not None: lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) @@ -1552,7 +1552,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # reallocation, so use the _list.py implementation. elif string.strcmp(lm_name, "append") == 0: if can >= 1 and cargs is not None: - ap_sha1: str = self._lookup_module_sha1("_list") + ap_sha1: char* = self._lookup_module_sha1("_list") if ap_sha1 is None: # Dependency module not compiled (_list not in the build chain): fail # fast, never silently skip append. @@ -1560,21 +1560,21 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if ap_sha1 is not None: # Extract the specialized class name: list.append's symbol is # {sha1}.list[AST*].append, not {sha1}.list.append. - ap_spec_nm: str = None + ap_spec_nm: char* = None ap_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) if ap_struct_ty is not None: ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) if ap_spec_nm is None: ap_spec_nm = "list" # Trigger generic specialization translation (idempotent). if trans is not None and ap_spec_nm is not None: - lbkt_ap: str = string.strchr(ap_spec_nm, '[') + lbkt_ap: char* = string.strchr(ap_spec_nm, '[') if lbkt_ap is not None: - rbkt_ap: str = string.strrchr(ap_spec_nm, ']') + rbkt_ap: char* = string.strrchr(ap_spec_nm, ']') if rbkt_ap is not None and rbkt_ap > lbkt_ap: base_len_ap: sizet = sizet(uint64(lbkt_ap) - uint64(ap_spec_nm)) arg_len_ap: sizet = sizet(uint64(rbkt_ap) - uint64(lbkt_ap) - 1) if base_len_ap > 0 and arg_len_ap > 0: - base_buf_ap: str = pool.alloc(base_len_ap + 1) - arg_buf_ap: str = pool.alloc(arg_len_ap + 1) + base_buf_ap: char* = pool.alloc(base_len_ap + 1) + arg_buf_ap: char* = pool.alloc(arg_len_ap + 1) if base_buf_ap is not None and arg_buf_ap is not None: string.strncpy(base_buf_ap, ap_spec_nm, base_len_ap) base_buf_ap[base_len_ap] = '\0' @@ -1583,14 +1583,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): args_ap: list[str]* = list[str](pool, 8) if args_ap is not None: # Comma-separated multiple type args (list[X] / dict[K, V]). - cur_ap: str = arg_buf_ap + cur_ap: char* = arg_buf_ap while cur_ap is not None: - comma_ap: str = string.strchr(cur_ap, ',') + comma_ap: char* = string.strchr(cur_ap, ',') if comma_ap is None: args_ap.append(cur_ap) break seg_len_ap: sizet = sizet(uint64(comma_ap) - uint64(cur_ap)) - seg_buf_ap: str = pool.alloc(seg_len_ap + 1) + seg_buf_ap: char* = pool.alloc(seg_len_ap + 1) if seg_buf_ap is not None: string.strncpy(seg_buf_ap, cur_ap, seg_len_ap) seg_buf_ap[seg_len_ap] = '\0' @@ -1600,7 +1600,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # Call name "{sha1}.{spec}.append": # sha1(16) + '.'(1) + spec + '.append'(7) + NUL(1) = spec + 25 ap_mlen: sizet = string.strlen(ap_sha1) + string.strlen(ap_spec_nm) + 26 - ap_mangled: str = pool.alloc(ap_mlen) + ap_mangled: char* = pool.alloc(ap_mlen) if ap_mangled is not None: viperlib.snprintf(ap_mangled, ap_mlen, "%s.%s.append", ap_sha1, ap_spec_nm) ap_item_node: ast.AST* = cargs.get(0) @@ -1622,7 +1622,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # current class from self, first MRO ancestor defining the method, no virtual. # ============================================================ - def _translate_super_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, method_name: str, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_super_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, method_name: char*, trans: HT.Translator*) -> mlirlite.Value*: """Translate super().method(args) as a static parent-class method call.""" if pool is None or builder is None or cl is None or method_name is None: return None if trans is None: return None @@ -1633,18 +1633,18 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if self_entry is None: self.Gen.TypeGenErr.fatal_error(cl, "super(): no self variable in the current scope (unavailable inside a static method)", "TypeError") return None - cur_class: str = self.Gen.VarGen.var_annot_class_name(self_entry) + cur_class: char* = self.Gen.VarGen.var_annot_class_name(self_entry) if cur_class is None: self.Gen.TypeGenErr.fatal_error(cl, "super() can only be used inside a class method (self has no annotated class name)") return None # 2. Walk the MRO, skipping self, for the first ancestor defining the method. - anc: str = None + anc: char* = None mro_sp: sizet* = self.Gen.StructGen.get_mro_chain(pool, cur_class) mi_sp: int = 1 while mro_sp is not None and mro_sp[mi_sp] != 0: - anc_sp: str = rawptr(mro_sp[mi_sp]) + anc_sp: char* = rawptr(mro_sp[mi_sp]) if anc_sp is not None: - probe_sp: str = pool.alloc(160) + probe_sp: char* = pool.alloc(160) if probe_sp is not None: viperlib.snprintf(probe_sp, 160, "%s.%s", anc_sp, method_name) if self.Gen.CallGenLeafKit.find_func_global(probe_sp) is not None: @@ -1652,7 +1652,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): break mi_sp += 1 if anc is None: - err_sp: str = pool.alloc(256) + err_sp: char* = pool.alloc(256) if err_sp is not None: viperlib.snprintf(err_sp, 256, "super(): the parent chain of current class %s does not define method %s", cur_class, method_name) self.Gen.TypeGenErr.fatal_error(cl, err_sp, "TypeError") @@ -1679,11 +1679,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if string.strcmp(anc, cur_class) != 0: anc_entry_sp: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(anc) if anc_entry_sp is not None and anc_entry_sp.FieldCount > 0: - first_name_sp: str = None + first_name_sp: char* = None for afi_sp in range(int(anc_entry_sp.FieldCount)): afe_sp: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(anc_entry_sp, afi_sp) if afe_sp is not None: - afn_sp: str = self.Gen.StructGen.get_field_name_ptr(afe_sp) + afn_sp: char* = self.Gen.StructGen.get_field_name_ptr(afe_sp) if afn_sp is not None and string.strcmp(afn_sp, "__vtable__") != 0: first_name_sp = afn_sp break @@ -1709,19 +1709,19 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mlirlite.module_ensure_opaque_for_type(mod, pool, anc_ptr_sp) self_arg = mlirlite.build_bitcast(builder, adj_sp, anc_ptr_sp) # 4. Find the parent method function and build the call name (SHA1-mangled). - anc_lookup: str = pool.alloc(160) + anc_lookup: char* = pool.alloc(160) if anc_lookup is None: return None viperlib.snprintf(anc_lookup, 160, "%s.%s", anc, method_name) found_func: mlirlite.Function* = self.find_func_in_module(mod, anc_lookup) - call_name: str = anc_lookup - anc_sha1_sp: str = self.Gen.StructGen.get_struct_sha1(anc) + call_name: char* = anc_lookup + anc_sha1_sp: char* = self.Gen.StructGen.get_struct_sha1(anc) if anc_sha1_sp is None: anc_sha1_sp = trans.ModuleSha1 if found_func is not None: - fname_sp: str = mlirlite.function_get_name(found_func) + fname_sp: char* = mlirlite.function_get_name(found_func) if fname_sp is not None: call_name = fname_sp else: if anc_sha1_sp is not None: - mangled_sp: str = self.Gen.FuncGenBase._mangle_name_with_sha1(anc_sha1_sp, anc_lookup) + mangled_sp: char* = self.Gen.FuncGenBase._mangle_name_with_sha1(anc_sha1_sp, anc_lookup) if mangled_sp is not None: call_name = mangled_sp # 5. Translate args and coerce to params (self is param 0, arg ai maps to ai+1). cargs_sp: list[ast.AST*]* = cl.args @@ -1793,7 +1793,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): return mlirlite.build_call(builder, call_name, head, arg_count_sp, ret_ty_sp, is_variadic_sp) # _recv_is_mixin_base - is the receiver used as a parent of a registered class? # Only a real direct parent can have its field area in a composite class layout. - def _recv_is_mixin_base(self, class_name: str) -> int: + def _recv_is_mixin_base(self, class_name: char*) -> int: """Is the receiver class a direct parent of any registered class; 1=yes / 0=no.""" if class_name is None: return 0 if self.Gen is None: return 0 @@ -1803,14 +1803,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if e is not None and e.Name is not None: pc: int = self.Gen.StructGen.get_parent_count(e.Name) for pj in range(int(pc)): - pn: str = self.Gen.StructGen.get_parent_name_at(e.Name, pj) + pn: char* = self.Gen.StructGen.get_parent_name_at(e.Name, pj) if pn is not None: if string.strcmp(pn, class_name) == 0: return 1 return 0 # _mixin_sibling_same_composite - do both classes share a composite class's MRO? # A registered class K whose MRO contains both is the necessary condition. - def _mixin_sibling_same_composite(self, pool: memhub.MemBuddy*, class_name: str, cand_name: str) -> int: + def _mixin_sibling_same_composite(self, pool: memhub.MemBuddy*, class_name: char*, cand_name: char*) -> int: """Do both classes share a registered composite class's MRO; 1=yes / 0=no.""" if class_name is None or cand_name is None or pool is None: return 0 if self.Gen is None: return 0 @@ -1824,7 +1824,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): has_cand: int = 0 mi: int = 0 while mro[mi] != 0: - nm: str = rawptr(mro[mi]) + nm: char* = rawptr(mro[mi]) if nm is not None: if string.strcmp(nm, class_name) == 0: has_self = 1 elif string.strcmp(nm, cand_name) == 0: has_cand = 1 @@ -1868,7 +1868,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): return 0 # _kwarg_name_matches - check whether a keyword arg name matches a param name. # Param names carry a "%" prefix in IR; compare after skipping it. - def _kwarg_name_matches(self, kw_arg: str, param_name: str) -> int: + def _kwarg_name_matches(self, kw_arg: char*, param_name: char*) -> int: """Check whether kwarg name kw_arg matches param param_name (skips '%' prefix).""" if kw_arg is None or param_name is None: return 0 start: sizet = 0 diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 116f064..b98e6f8 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -54,7 +54,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _apply_struct_defaults - apply struct field default values after zeroinitializer and # before explicit args (which later override); translate + store each field with a default. - def _apply_struct_defaults(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: str, tmp: mlirlite.Value*, trans: HT.Translator*, is_volatile: int = 0): + def _apply_struct_defaults(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: char*, tmp: mlirlite.Value*, trans: HT.Translator*, is_volatile: int = 0): """Apply struct field default values; is_volatile=1 keeps ctor writes volatile""" # locate the entry by type pointer to avoid cross-module same-name find_struct mistakes entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) @@ -82,9 +82,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): zero_arr2: mlirlite.Value* = mlirlite.ConstZero(pool, fe.Ty) if zero_arr2 is not None: mlirlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile) # owner_ctx only serves the empty-element fail-fast message (class + field + index) - sd_ctx: str = pool.alloc(192) + sd_ctx: char* = pool.alloc(192) if sd_ctx is not None: - fname_sd: str = fe.Name + fname_sd: char* = fe.Name if fname_sd is None: fname_sd = "?" viperlib.snprintf(sd_ctx, 192, "Class %s field %s (struct ctor defaults):", class_name, fname_sd) # arr_ty_opt = fe.Ty: same reason as ClassGenVTable (the GEP value may carry no pointee type) @@ -108,7 +108,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _translate_struct_ctor - struct constructor Point(10, 20): alloca, zeroinit, per-field # GEP + store (or __new__/__before_init__/__init__ for OOP structs), then load. - def _translate_struct_ctor(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: str, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: + def _translate_struct_ctor(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: char*, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: """Translate a struct constructor; stores args by field; is_volatile=1 marks writes volatile""" # Create the temporary alloca, ensuring the full cross-module struct definition is # available in this module. @@ -142,7 +142,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # Cross-module OOP inference: IsOOP may be unset (Phase1 cache skipped # _translate_oop_methods). Check for ClassName.__init__ in the module or global defaults table. if is_oop == 0 and class_name is not None: - init_lookup_name: str = pool.alloc(128) + init_lookup_name: char* = pool.alloc(128) if init_lookup_name is not None: viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name) # option 1: check the current module's function declarations @@ -205,7 +205,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if ctor_entry is not None and ctor_entry.IsOOP != 0: bi_ok = 1 if bi_ok == 0 and ctor_entry is not None and ctor_entry.HasInit != 0: bi_ok = 1 if bi_ok == 0 and class_name is not None: - bi_lk: str = pool.alloc(160) + bi_lk: char* = pool.alloc(160) if bi_lk is not None: viperlib.snprintf(bi_lk, 160, "%s.__init__", class_name) if self.find_func_in_module(mod, bi_lk) is not None: bi_ok = 1 @@ -215,7 +215,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): bi_mro: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) bi_mi: int = 1 while bi_mro is not None and bi_mro[bi_mi] != 0: - bi_anc: str = rawptr(bi_mro[bi_mi]) + bi_anc: char* = rawptr(bi_mro[bi_mi]) if bi_anc is not None and string.strcmp(bi_anc, class_name) != 0: bi_ae: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(bi_anc) if bi_ae is not None and bi_ae.HasInit != 0: @@ -267,7 +267,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): for fi in range(int(ctor_entry.FieldCount)): cand_fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(ctor_entry, fi) if cand_fe is None: continue - cand_name: str = self.Gen.StructGen.get_field_name_ptr(cand_fe) + cand_name: char* = self.Gen.StructGen.get_field_name_ptr(cand_fe) if cand_name is not None and string.strcmp(cand_name, "__vtable__") == 0: continue if target_idx == ai: fe = cand_fe @@ -335,7 +335,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _translate_renum_construct - REnum variant ctor (ClassName.Variant(args...)): alloca, # zeroinit, store __tag and payload fields, return the pointer. - def _translate_renum_construct(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: str, variant_name: str, tag_value: int, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: + def _translate_renum_construct(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, class_name: char*, variant_name: char*, tag_value: int, cargs: list[ast.AST*]*, can: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: """Build a REnum variant instance; returns a pointer to the alloca""" if pool is None or builder is None or class_name is None: return None @@ -369,7 +369,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): tag_field: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(renum_entry, 0) tag_field_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) if tag_field is not None and tag_field.Ty is not None: tag_field_ty = tag_field.Ty - tag_name_buf: str = pool.alloc(32) + tag_name_buf: char* = pool.alloc(32) if tag_name_buf is not None: viperlib.snprintf(tag_name_buf, 32, "%d", tag_value) tag_const: mlirlite.Value* = mlirlite.ConstInt(pool, tag_field_ty, tag_value, tag_name_buf if tag_name_buf is not None else "0") tag_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, renum_ty, tag_field_ty, tmp, 0) @@ -408,7 +408,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # stack(含 stack slife)→ 帧内 alloca,随帧消失,不产生 free; # memgr(x) slife → 归还池(D6 待定),本阶段不接管。 # _new_is_nll_demotable - §13 NLL:可降级为"帧对象"的 `new heap`(判据见 Debugger/ownership-and-new.md §13.2) - def _new_is_nll_demotable(self, trans: HT.Translator*, rhs: ast.AST*, var_name: str) -> int: + def _new_is_nll_demotable(self, trans: HT.Translator*, rhs: ast.AST*, var_name: char*) -> int: """1 = 该 `new` 可当帧对象处理(生命期按 FRAME、出口释放复用 slife 通道);0 = 不必/判不定。 只降级"堆且**未显式**指定生命期"的:显式 `hlife` 是用户对自由生命期的要求,不动; @@ -467,7 +467,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if src == ast.NEW_SRC_STACK and life == ast.NEW_LIFE_HLIFE: self.Gen.TypeGenErr.fatal_error(new_node, "`new stack hlife` is contradictory: stack storage cannot outlive its frame; use `new stack slife`, or `heap`/`memgr(x)`", "LifetimeError") return None - class_name: str = self.Gen.ExprGenBase.get_func_name(new_node.func) + class_name: char* = self.Gen.ExprGenBase.get_func_name(new_node.func) # REnum 变体构造:`new [desc] Qual.Variant(args)`(如 new memgr(pool) LLVMType.Int(32))。 # callee 是 Attribute 且限定名 Qual 为已注册 REnum 类、Variant 命中该类的变体表时,把 # class_name 归一到 **Qual(REnum 类名)**:下方 get_struct_type 命中的正是 REnum 的 @@ -476,7 +476,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 不归一(Qual 非 REnum / 变体缺失)时保持原样,由下方基本类型路径定夺 / fail-fast。 if class_name is not None and new_node.func is not None and new_node.func.kind() == ast.ASTKind.Attribute: _rn_at: ast.Attribute* = ast.Attribute*(new_node.func) - _rn_qual: str = None + _rn_qual: char* = None if _rn_at.value is not None: if _rn_at.value.kind() == ast.ASTKind.Name: _rn_qual = ast.Name*(_rn_at.value).id @@ -558,7 +558,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # heap/memgr → 按 sizeof(T) 分配(复用既有 memgr 通道) # 有实参的标量(`new stack int(5)`)在这里 fail-fast:本路径刻意只做"取存储", # 不引入"标量构造"的第二套语义(要初值就 `new … int` 之后赋值)。 - def _translate_new_primitive(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, new_node: ast.New*, class_name: str, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_new_primitive(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, new_node: ast.New*, class_name: char*, trans: HT.Translator*) -> mlirlite.Value*: """`new` 基本类型(标量):取存储 + 零初始化;返回 T*(失败返回 None,均 fail-fast)""" prim_ty: mlirlite.LLVMType* = None if new_node.func is not None: @@ -578,7 +578,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): elem_ty = elem_a case _: pass - nm: str = class_name + nm: char* = class_name if nm is None: nm = "?" if is_scalar == 0: if class_name is None: @@ -642,7 +642,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if mv is None: self.Gen.TypeGenErr.fatal_error(mgr_node, "`memgr(x)`: cannot translate the manager expression", "TypeError") return None - mgr_cls: str = None + mgr_cls: char* = None mty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(mv) if mty is not None: mgr_cls = self.Gen.StructGen.get_class_name_by_type(pool, mty) if mgr_cls is None: @@ -656,7 +656,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _translate_struct_ctor_kw - struct constructor with keyword args: Point(x=10, y=20) or # Point(10, y=20); positional args map by field index, keywords by field name. - def _translate_struct_ctor_kw(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: str, cargs: list[ast.AST*]*, can: sizet, keywords: list[ast.AST*]*, kw_count: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: + def _translate_struct_ctor_kw(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, struct_ty: mlirlite.LLVMType*, class_name: char*, cargs: list[ast.AST*]*, can: sizet, keywords: list[ast.AST*]*, kw_count: sizet, trans: HT.Translator*, is_volatile: int = 0) -> mlirlite.Value*: """Struct constructor for keyword arguments; is_volatile=1 marks writes volatile""" # Create the temporary alloca, ensuring the full cross-module struct definition is # available in this module. @@ -691,7 +691,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # Cross-module OOP inference: IsOOP may be unset (Phase1 cache skipped # _translate_oop_methods). Check for ClassName.__init__ in the module or global defaults table. if is_oop == 0 and class_name is not None: - kw_init_lookup: str = pool.alloc(128) + kw_init_lookup: char* = pool.alloc(128) if kw_init_lookup is not None: viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name) # option 1: check the current module's function declarations @@ -818,7 +818,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # Handle keyword args (lookup by field name). # Get the SHA1 from kw_entry (avoid cross-module same-name find_struct mistakes). - kw_sha1: str = None + kw_sha1: char* = None if kw_entry is not None: kw_sha1 = kw_entry.ModuleSha1 for ki in range(int(kw_count)): kw: ast.Keyword* = ast.Keyword*(keywords.get(ki)) @@ -897,15 +897,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # Generic-instantiation helper: extract type-argument names from a Subscript slice. # _get_type_name_from_annotation now lives in HandlesType.py (supports BinOp/Attribute). - def _extract_type_args_from_slice(self, pool: memhub.MemBuddy*, slice_node: ast.AST*, from_imports: str = None) -> list[str]*: + def _extract_type_args_from_slice(self, pool: memhub.MemBuddy*, slice_node: ast.AST*, from_imports: char* = None) -> list[str]*: """Extract type-argument names from a Subscript.slice; normalised when from_imports is set""" if slice_node is None or pool is None: return None - # elem_size=8: str is an i8* pointer (8 bytes); with 4, append writes 8 bytes at a + # elem_size=8: char* is an i8* pointer (8 bytes); with 4, append writes 8 bytes at a # 4-byte stride and the second element overwrites the first -> get returns a junk pointer. result: list[str]* = list[str](pool, 8) k: int = slice_node.kind() - tn_raw: str = None - tn: str = None + tn_raw: char* = None + tn: char* = None if k == ast.ASTKind.Tuple: tp: ast.Tuple* = ast.Tuple*(slice_node) elts: list[ast.AST*]* = tp.elts @@ -927,10 +927,10 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _ptr_layer_type_arg - add the pointer layer (`*`) to inferred type args so the ctor side # matches the annotation-side canonical form `{sha}.Type*`; non-class names pass through. - def _ptr_layer_type_arg(self, pool: memhub.MemBuddy*, cls_nm: str, ptr_level: int, from_imports: str) -> str: + def _ptr_layer_type_arg(self, pool: memhub.MemBuddy*, cls_nm: char*, ptr_level: int, from_imports: char*) -> str: """Map an annotation class name to a type-arg text; add `*` per PtrLevel, non-class names unchanged""" if cls_nm is None: return None - res_pl: str = self.Gen.TypeGenResolve._norm_type_arg_name(pool, cls_nm, from_imports) + res_pl: char* = self.Gen.TypeGenResolve._norm_type_arg_name(pool, cls_nm, from_imports) if res_pl is None: res_pl = cls_nm if ptr_level <= 0: return res_pl # non-class names (no SHA1 prefix, e.g. typedef "VOIDPTR" / bare marker "PtrT") keep the pointer layer @@ -944,7 +944,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): lvl_pl -= 1 return res_pl - def _infer_generic_ctor_type_arg(self, pool: memhub.MemBuddy*, arg_node: ast.AST*, class_name: str, trans: HT.Translator*) -> str: + def _infer_generic_ctor_type_arg(self, pool: memhub.MemBuddy*, arg_node: ast.AST*, class_name: char*, trans: HT.Translator*) -> str: """Infer a generic type-arg name from a ctor arg AST (static AST only, no IR)""" if pool is None or arg_node is None: self.Gen.TypeGenErr.fatal_error(None, f"Cannot infer the type argument of generic class '{class_name}' from the argument; annotate explicitly, e.g. {class_name}[Type](...)", "TypeError") @@ -969,12 +969,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if cty_c is not None: # Signedness comes from the callee's source text (LLVM iN/uN are identical), # reusing spec_sign_of_annot (whitelist + TypedefT chain fallback). - callee_txt_c: str = None + callee_txt_c: char* = None if fk_c == ast.ASTKind.Name: callee_txt_c = ast.Name*(cl_f.func).id else: callee_txt_c = ast.Attribute*(cl_f.func).attr sign_c: int = TSpec.TS_SIGN_UNKNOWN if callee_txt_c is not None: sign_c = self.Gen.TypeGenCType.spec_sign_of_annot(callee_txt_c, 0) - ta_c: str = self.Gen.ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty(pool, cty_c, sign_c) + ta_c: char* = self.Gen.ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty(pool, cty_c, sign_c) if ta_c is not None: return ta_c # A cast call whose callee does not resolve to a scalar type: fail-fast # (return None -> caller fail-fasts). @@ -989,7 +989,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if ve_i is not None: # Route the annotation class name through _ptr_layer_type_arg: after # _norm_type_arg_name, add `*` when the value type is a pointer (Spec.PtrLevel>0). - cn_nm_i: str = self.Gen.VarGen.var_annot_class_name(ve_i) + cn_nm_i: char* = self.Gen.VarGen.var_annot_class_name(ve_i) pl_nm_i: int = 0 if ve_i.Spec is not None: pl_nm_i = ve_i.Spec.PtrLevel return self._ptr_layer_type_arg(pool, cn_nm_i, pl_nm_i, trans._from_imports) @@ -999,16 +999,16 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if k == ast.ASTKind.Attribute: # Same: add `*` when the field value type is a pointer (FieldEntry.Spec.PtrLevel>0). # _resolve_attr_field_entry is read-only, supports one level; deeper chains keep the old behaviour. - cn_at_i: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node) + cn_at_i: char* = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node) pl_at_i: int = 0 fe_at_i: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, arg_node) if fe_at_i is not None and fe_at_i.Spec is not None: pl_at_i = fe_at_i.Spec.PtrLevel - fi_at_i: str = None + fi_at_i: char* = None if trans is not None: fi_at_i = trans._from_imports return self._ptr_layer_type_arg(pool, cn_at_i, pl_at_i, fi_at_i) return None - def _annotation_refers_type_param(self, node: ast.AST*, tp_name: str) -> int: + def _annotation_refers_type_param(self, node: ast.AST*, tp_name: char*) -> int: """Whether an annotation refers to type parameter tp_name (1=yes / 0=no)""" if node is None or tp_name is None: return 0 k: int = node.kind() @@ -1022,7 +1022,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): return self._annotation_refers_type_param(bop_a.right, tp_name) return 0 - def _get_ctor_init_params(self, class_name: str) -> list[ast.AST*]*: + def _get_ctor_init_params(self, class_name: char*) -> list[ast.AST*]*: """Return the generic template __init__ parameter list (including self); None if unavailable""" if class_name is None: return None template_cd: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(class_name) @@ -1041,7 +1041,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): return fargs.args return None - def _find_ctor_type_param_param_index(self, class_name: str, tp_name: str) -> int: + def _find_ctor_type_param_param_index(self, class_name: char*, tp_name: char*) -> int: """Parameter index in the template __init__ annotated with tp_name (incl. self, 0-based); -1 if not found""" if class_name is None or tp_name is None: return -1 plist: list[ast.AST*]* = self._get_ctor_init_params(class_name) @@ -1057,13 +1057,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if self._annotation_refers_type_param(ag.annotation, tp_name) != 0: return int(pi) return -1 - def _find_ctor_type_param_arg_index(self, class_name: str, tp_name: str) -> int: + def _find_ctor_type_param_arg_index(self, class_name: char*, tp_name: char*) -> int: """Positional-arg index for the param annotated with tp_name in the template __init__; -1 if not found""" pi_arg: int = self._find_ctor_type_param_param_index(class_name, tp_name) if pi_arg < 0: return -1 return pi_arg - 1 - def _ctor_init_arg_slot_by_name(self, class_name: str, kw_name: str) -> int: + def _ctor_init_arg_slot_by_name(self, class_name: char*, kw_name: char*) -> int: """Map a keyword arg name to its non-self param slot; -1 if the template or name is missing""" if class_name is None or kw_name is None: return -1 plist_sb: list[ast.AST*]* = self._get_ctor_init_params(class_name) @@ -1079,7 +1079,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if ag_sb.arg is not None and string.strcmp(ag_sb.arg, kw_name) == 0: return int(pi_sb) - 1 return -1 - def _find_ctor_type_param_kw_arg_index(self, class_name: str, tp_name: str, keywords: list[ast.AST*]*, kw_count: sizet, pos_count: int) -> int: + def _find_ctor_type_param_kw_arg_index(self, class_name: char*, tp_name: char*, keywords: list[ast.AST*]*, kw_count: sizet, pos_count: int) -> int: """Keyword-only construction: keyword-arg index for type param tp_name; -1 if not found""" if class_name is None or tp_name is None or keywords is None: return -1 pi_kw: int = self._find_ctor_type_param_param_index(class_name, tp_name) @@ -1100,7 +1100,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if string.strcmp(kw_tp.arg, ag_kw.arg) == 0: return int(ki_kw) return -1 - def _infer_ctor_type_args_from_ctx(self, pool: memhub.MemBuddy*, trans: HT.Translator*, class_name: str, tp_count: int, cl: ast.Call*) -> list[str]*: + def _infer_ctor_type_args_from_ctx(self, pool: memhub.MemBuddy*, trans: HT.Translator*, class_name: char*, tp_count: int, cl: ast.Call*) -> list[str]*: """Infer generic ctor type args from the assignment-target or return annotation context; None if N/A""" if pool is None or trans is None or class_name is None or cl is None: return None if tp_count <= 0: return None @@ -1130,7 +1130,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if len(type_args_ctx) != sizet(tp_count): return None return type_args_ctx - def _translate_generic_ctor_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, spec_name: str, cl: ast.Call*, trans: HT.Translator*, tmpl_name: str = None) -> mlirlite.Value*: + def _translate_generic_ctor_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, spec_name: char*, cl: ast.Call*, trans: HT.Translator*, tmpl_name: char* = None) -> mlirlite.Value*: """Translate a generic-class ctor call: __new__ + __before_init__ + __init__""" if pool is None or builder is None or mod is None or spec_name is None or cl is None: return None @@ -1249,7 +1249,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if gi_has_init == 0: # 特化类的 HasInit 可能没被传播:再按非泛型路径同口径查"该方法是否真的存在" # (模块内声明 或 全局默认参数表),避免有 __init__ 的泛型类被漏掉。 - init_lk: str = pool.alloc(256) + init_lk: char* = pool.alloc(256) if init_lk is not None: viperlib.snprintf(init_lk, 256, "%s.__init__", spec_name) if self.find_func_in_module(mod, init_lk) is not None: gi_has_init = 1 @@ -1272,7 +1272,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): for fi_sf in range(int(struct_entry.FieldCount)): cand_sf: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(struct_entry, fi_sf) if cand_sf is None: continue - cn_sf: str = self.Gen.StructGen.get_field_name_ptr(cand_sf) + cn_sf: char* = self.Gen.StructGen.get_field_name_ptr(cand_sf) if cn_sf is not None and string.strcmp(cn_sf, "__vtable__") == 0: continue if tidx_sf == ai_sf: fe_sf = cand_sf diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index c21f854..ab08184 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -27,14 +27,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # _tc_h0_generic_func - generic function call: infer/specialize type args, then emit the call. # Must run before normal function/constructor dispatch; hit_box marks handled void calls. - def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: + def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: if cl is None or trans is None: return None if self.Gen.ClassGenGeneric.GenericFuncKeys is None: return None if cl.func is None: return None # ---- Classify the generic call shape + template name / explicit type args ---- - tpl_name: str = None + tpl_name: char* = None explicit_slice: ast.AST* = None - tpl_mod_sha1: str = None + tpl_mod_sha1: char* = None is_attr_call: int = 0 fk: int = cl.func.kind() if fk == ast.ASTKind.Subscript: @@ -57,20 +57,20 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): tpl_name = at.attr if tpl_name is None: return None # ---- Resolve template key "{sha1}.{fname}": module-qualified > local > from_imports ---- - tpl_key: str = None + tpl_key: char* = None if is_attr_call != 0: # Module-qualified call: only accept the key under that module's SHA1 if tpl_mod_sha1 is not None: - cand_q: str = self._generic_func_key(pool, tpl_mod_sha1, tpl_name) + cand_q: char* = self._generic_func_key(pool, tpl_mod_sha1, tpl_name) if self.Gen.ClassGenGeneric._find_generic_func_template(cand_q) is not None: tpl_key = cand_q else: if trans.ModuleSha1 is not None: - cand_l: str = self._generic_func_key(pool, trans.ModuleSha1, tpl_name) + cand_l: char* = self._generic_func_key(pool, trans.ModuleSha1, tpl_name) if self.Gen.ClassGenGeneric._find_generic_func_template(cand_l) is not None: tpl_key = cand_l if tpl_key is None and trans._from_imports is not None: - imp_sha: str = self._lookup_mod_sha1(pool, trans._from_imports, tpl_name, 0) + imp_sha: char* = self._lookup_mod_sha1(pool, trans._from_imports, tpl_name, 0) if imp_sha is not None: - cand_f: str = self._generic_func_key(pool, imp_sha, tpl_name) + cand_f: char* = self._generic_func_key(pool, imp_sha, tpl_name) if self.Gen.ClassGenGeneric._find_generic_func_template(cand_f) is not None: tpl_key = cand_f if tpl_key is None: return None template_fd: ast.FunctionDef* = self.Gen.ClassGenGeneric._find_generic_func_template(tpl_key) @@ -94,8 +94,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if type_args is None: return None tpi: sizet for tpi in range(int(tp_count)): - tp_name: str = tp_names.get(tpi) - ta: str = None + tp_name: char* = tp_names.get(tpi) + ta: char* = None slot: int = self.Gen.ClassGenGeneric._find_generic_func_param_slot(template_fd, tp_name) if slot >= 0 and sizet(slot) < can: ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, cargs.get(sizet(slot)), tpl_name, trans) if ta is None and slot >= 0: @@ -110,18 +110,18 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return None type_args.append(ta) # ---- Specialize ---- - spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_function(trans, tpl_key, type_args) + spec_name: char* = self.Gen.ClassGenGeneric._specialize_generic_function(trans, tpl_key, type_args) if spec_name is None: self.Gen.TypeGenErr.fatal_error(cl, f"Generic function '{tpl_name}': specialization failed", "TypeError") return None # ---- Emit call ---- return self._emit_generic_func_call(pool, builder, mod, trans, cl, spec_name, cargs, can, hit_box) - def _generic_func_key(self, pool: memhub.MemBuddy*, sha1: str, name: str) -> str: + def _generic_func_key(self, pool: memhub.MemBuddy*, sha1: char*, name: char*) -> str: """Build the generic function template key "{sha1}.{name}" in a new buffer.""" if sha1 is None or name is None: return None klen: sizet = string.strlen(sha1) + string.strlen(name) + 2 - kbuf: str = pool.alloc(klen) + kbuf: char* = pool.alloc(klen) if kbuf is None: return None viperlib.snprintf(kbuf, klen, "%s.%s", sha1, name) return kbuf @@ -147,7 +147,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if string.strcmp(kw.arg, ag.arg) == 0: return int(ki) return -1 - def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: + def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: """Emit the specialized-function call, coercing args to the specialized param types.""" func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name) if func is None: @@ -188,7 +188,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # reads its first field as a string and emits illegal IR. Use the looked-up symbol name. return mlirlite.build_call(builder, spec_name, head, int(can), ret_ty, 0) - def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: + def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: """Compile-time super()/ctraits detection; sets hit_box on interception, else returns None.""" # super().method(args) -> static call to the parent method. Must intercept before attribute # dispatch, else Call(super) is treated as a plain function call and lookup hits self/vtable. @@ -220,7 +220,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.const_int32(pool, 0) return None - def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: + def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: """Special __asm__/__llvmir__ calls; marks hit_box for void calls, else returns None.""" # Retired c.* pointer builtins: fail fast with the replacement syntax. if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: @@ -292,7 +292,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return self.Gen.AsyncGen.translate_coro_gather(builder, pool, mod, cl, trans) return None - def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: + def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: """stdarg sugar and str/int/bool built-in casts; returns None when unmatched.""" # stdarg sugar (va_arg / arg / va_start / va_end): these are declared as pass bodies in # stdarg.vp and handled here at translation time by emitting LLVM va_arg / intrinsic calls. @@ -306,10 +306,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): elif string.strcmp(func_name, "va_end") == 0: return self.Gen.CallGenVa._translate_va_end_sugar(pool, builder, mod, cargs, can, funcs_ptr, func_count, trans) - # Builtin casts: str(x)/bytes(x) -> i8*, int(x) -> i32, equivalent to (str)(x)/(int32)(x). + # Builtin casts: char*(x)/bytes(x) -> i8*, int(x) -> i32, equivalent to (str)(x)/(int32)(x). # In generic contexts T(x) first resolves T to a concrete type, then follows this path. if func_name is not None and can == 1: - cast_fn_name: str = self.Gen.TypeGenBase.resolve_generic_type_name(func_name) + cast_fn_name: char* = self.Gen.TypeGenBase.resolve_generic_type_name(func_name) if string.strcmp(cast_fn_name, "str") == 0 or string.strcmp(cast_fn_name, "bytes") == 0: # str(x) / bytes(x) → i8* (bitcast) cast_arg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) @@ -354,7 +354,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return None return None - def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: + def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: """Builtin / typedef type casts; returns None when unmatched.""" # Module-qualified typedef cast (posix.mode_t(mode), win32.win32base.LPCWSTR(v), ...): the # callee is Attribute(, typedef); non-typedef names still go to the module call. @@ -362,7 +362,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): mt_at: ast.Attribute* = ast.Attribute*(cl.func) if mt_at.attr is not None: # Module path supports both `mod.T` and nested `pkg.mod.T`. - mt_mod_path: str = None + mt_mod_path: char* = None if mt_at.value is not None and mt_at.value.kind() == ast.ASTKind.Name: mt_mod_nm: ast.Name* = ast.Name*(mt_at.value) mt_mod_path = mt_mod_nm.id @@ -371,23 +371,23 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if mt_mod_path is not None: mod_td_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_builtin_type(pool, func_name) if mod_td_ty is None: - mod_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(func_name) + mod_td_str: char* = self.Gen.TypeGenCType.lookup_ctypedef(func_name) if mod_td_str is None or self.Gen.TypeGenCType.is_ctypedef_found() == 0: # Library typedef closure may not be injected yet: scan the module source. mod_td_str = self.Gen.TypeGenResolve._lookup_library_typedef(pool, mt_mod_path, func_name) if mod_td_str is not None: mod_td_ast: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, mod_td_str, 0) if mod_td_ast is not None: - mod_imp_td: str = None - mod_fi_td: str = None + mod_imp_td: char* = None + mod_fi_td: char* = None if trans is not None: mod_imp_td = trans._imported_modules mod_fi_td = trans._from_imports mod_td_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, mod_td_ast, mod_imp_td, mod_fi_td, trans, 0) if mod_td_ty is None: # Final fallback: the shared typedef resolver also scans stdint/win32base. - mod_imp_fb: str = None - mod_fi_fb: str = None + mod_imp_fb: char* = None + mod_fi_fb: char* = None if trans is not None: mod_imp_fb = trans._imported_modules mod_fi_fb = trans._from_imports @@ -399,7 +399,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Bare typedef casts (BYTEPTR, HANDLE, CHARPTR, ...): all TypedefT names and builtin primitives # are castable. In generic contexts T(x) first resolves T, then goes through resolve_typedef_or_map. if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: - bare_fn_name: str = self.Gen.TypeGenBase.resolve_generic_type_name(func_name) + bare_fn_name: char* = self.Gen.TypeGenBase.resolve_generic_type_name(func_name) bare_ty: mlirlite.LLVMType* = None # Builtin names resolved from generic context (T->"double"/"float"): float must map to # f32, not f64. @@ -408,8 +408,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): else: # Prefer the TypedefT dynamic table (library typedef casts); on miss fall back to # map_builtin_type. - bare_imp_c: str = None - bare_fi_c: str = None + bare_imp_c: char* = None + bare_fi_c: char* = None if trans is not None: bare_imp_c = trans._imported_modules bare_fi_c = trans._from_imports @@ -419,8 +419,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if bare_ty is None and string.strcmp(bare_fn_name, func_name) != 0: gp_ast: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, bare_fn_name, 0) if gp_ast is not None: - imp_gp: str = None - fi_gp: str = None + imp_gp: char* = None + fi_gp: char* = None if trans is not None: imp_gp = trans._imported_modules fi_gp = trans._from_imports @@ -457,7 +457,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return None - def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: + def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: """__sizeof__/len/isinstance built-ins; returns None when unmatched.""" # Detect ClassName.__sizeof__() and return the struct size constant (i64); it is a builtin, # not a cross-module call. Supports e.g. Argument.__sizeof__() and module-qualified classes. @@ -465,7 +465,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): sz_at: ast.Attribute* = ast.Attribute*(cl.func) if sz_at.attr is not None and string.strcmp(sz_at.attr, "__sizeof__") == 0: if sz_at.value is not None and can == 0: - sz_cls_name: str = None + sz_cls_name: char* = None sz_vk: int = sz_at.value.kind() if sz_vk == ast.ASTKind.Name: sz_cls_nm2: ast.Name* = ast.Name*(sz_at.value) @@ -480,7 +480,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): sz_inner_nm: ast.Name* = ast.Name*(sz_inner_at.value) if sz_inner_nm.id is not None: sz_full_len: sizet = string.strlen(sz_inner_nm.id) + 1 + string.strlen(sz_inner_at.attr) + 1 - sz_full_buf: str = pool.alloc(sz_full_len) + sz_full_buf: char* = pool.alloc(sz_full_len) if sz_full_buf is not None: sz_full_buf[0] = '\0' string.strcat(sz_full_buf, sz_inner_nm.id) @@ -488,10 +488,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): string.strcat(sz_full_buf, sz_inner_at.attr) sz_cls_name = sz_full_buf elif sz_inner_at.value.kind() == ast.ASTKind.Attribute: - sz_mod_path: str = self.Gen.ExprGenAttr._attr_module_path_str(pool, sz_inner_at.value) + sz_mod_path: char* = self.Gen.ExprGenAttr._attr_module_path_str(pool, sz_inner_at.value) if sz_mod_path is not None: sz_full_len2: sizet = string.strlen(sz_mod_path) + 1 + string.strlen(sz_inner_at.attr) + 1 - sz_full_buf2: str = pool.alloc(sz_full_len2) + sz_full_buf2: char* = pool.alloc(sz_full_len2) if sz_full_buf2 is not None: sz_full_buf2[0] = '\0' string.strcat(sz_full_buf2, sz_mod_path) @@ -500,10 +500,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): sz_cls_name = sz_full_buf2 # Resolve the struct type: type-name hit -> generic specialization (Stack[T]) -> receiver type (self/obj) sz_resolved_ty: mlirlite.LLVMType* = None - sz_resolved_name: str = sz_cls_name + sz_resolved_name: char* = sz_cls_name if sz_cls_name is not None: # Replace generic type parameter T: T.__sizeof__() -> int.__sizeof__() - sz_orig: str = sz_cls_name + sz_orig: char* = sz_cls_name sz_cls_name = self.Gen.TypeGenBase.resolve_generic_type_name(sz_cls_name) # Fallback when the TypeGenBase context is empty (template tp_names expired # across phases): replace T using trans's generic mapping. @@ -511,9 +511,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): gp_n: sizet = len(trans.GenericTypeParamNames) gp_i: sizet for gp_i in range(int(gp_n)): - gpn: str = trans.GenericTypeParamNames.get(gp_i) + gpn: char* = trans.GenericTypeParamNames.get(gp_i) if gpn is not None and string.strcmp(sz_orig, gpn) == 0: - gta: str = trans.GenericTypeArgs.get(gp_i) + gta: char* = trans.GenericTypeArgs.get(gp_i) if gta is not None: sz_cls_name = gta break sz_resolved_name = sz_cls_name @@ -528,10 +528,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == '*': return mlirlite.const_int64(pool, 8) # Save the full name (with module prefix) for exact module matching: stripping it # lets get_struct_type globally match a same-named class from another module. - sz_full_name: str = sz_cls_name + sz_full_name: char* = sz_cls_name # Strip the module prefix: the Viper parser yields Name(id="int") rather than # Attribute, so manually take the last class-name component. - dot_pos: str = string.strrchr(sz_cls_name, '.') + dot_pos: char* = string.strrchr(sz_cls_name, '.') if dot_pos is not None: sz_cls_name = dot_pos + 1 # [Phase 3] Unified size convention: resolve library typedefs first, only then # use the hardcoded table. Pass trans's imports so from-import alias chains resolve. @@ -567,16 +567,16 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Module-qualified classes match the defining module exactly, preventing a # same-named class from another module from being matched globally. if sz_full_name is not None: - szf_dot: str = string.strrchr(sz_full_name, '.') + szf_dot: char* = string.strrchr(sz_full_name, '.') if szf_dot is not None: szf_mod_len: sizet = sizet(uint64(szf_dot) - uint64(sz_full_name)) - szf_mod: str = pool.alloc(szf_mod_len + 1) + szf_mod: char* = pool.alloc(szf_mod_len + 1) if szf_mod is not None: string.strncpy(szf_mod, sz_full_name, szf_mod_len) szf_mod[szf_mod_len] = '\0' # Module-qualified builtin names are already handled by the builtin/size table. if szf_mod is not None: - szf_sha1: str = self.Gen.StructGen._resolve_module_sha1(szf_mod, trans._from_imports if trans is not None else None) + szf_sha1: char* = self.Gen.StructGen._resolve_module_sha1(szf_mod, trans._from_imports if trans is not None else None) if szf_sha1 is not None: szf_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1) if szf_entry is not None and szf_entry.Ty is not None: sz_resolved_ty = szf_entry.Ty @@ -595,9 +595,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): gai_sz: sizet = len(gen_args_sz) gai2_sz: sizet = 0 for gai2_sz in range(int(gai_sz)): - gres_sz: str = self.Gen.TypeGenBase.resolve_generic_type_name(gen_args_sz.get(gai2_sz)) + gres_sz: char* = self.Gen.TypeGenBase.resolve_generic_type_name(gen_args_sz.get(gai2_sz)) gargs_resolved.append(gres_sz) - spec_sz: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_nm_sz.id, gargs_resolved) + spec_sz: char* = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_nm_sz.id, gargs_resolved) if spec_sz is not None: sz_resolved_name = spec_sz sz_resolved_ty = self.Gen.StructGen.get_struct_type(spec_sz) @@ -686,7 +686,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # strlen on the first field). list containers inline-read __count__; plain classes call {Class}.__len__. len_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(len_val) if len_struct_ty is not None: - len_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, len_struct_ty) + len_cls_nm: char* = self.Gen.StructGen.get_class_name_by_type(pool, len_struct_ty) if len_cls_nm is None: self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type inference failed (unknown struct class name)", "TypeError") # list builtin __len__: read __count__ (GEP offset 1, i64). Narrow len_arg_node # to ast.Call* explicitly, since passing a base pointer to a derived param is banned. @@ -696,13 +696,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): idx_one_lb: mlirlite.Value* = mlirlite.const_int64(pool, 1) cnt_ptr_lb: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty_lb, len_val, idx_one_lb) if cnt_ptr_lb is not None: return mlirlite.build_load(builder, i64_ty_lb, cnt_ptr_lb) - len_lookup: str = pool.alloc(128) + len_lookup: char* = pool.alloc(128) if len_lookup is not None: viperlib.snprintf(len_lookup, 128, "%s.__len__", len_cls_nm) len_fn2: mlirlite.Function* = self.find_func_in_module(mod, len_lookup) if len_fn2 is not None: len_ret_ty2: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(len_fn2) - len_fn_name2: str = mlirlite.function_get_name(len_fn2) + len_fn_name2: char* = mlirlite.function_get_name(len_fn2) if len_ret_ty2 is not None and len_fn_name2 is not None: # Align the self parameter type (bitcast to the method's first param) len_self_arg2: mlirlite.Value* = len_val @@ -714,12 +714,12 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.build_call(builder, len_fn_name2, len_self_arg2, 1, len_ret_ty2, 0) # len_fn2 miss (cross-module method): build the exact name {sha1}.{cls}.__len__ # from the struct's module sha1, resolve the return type from text.ll/vpi, then call. - len_cls_sha1_x: str = self.Gen.StructGen.get_struct_sha1(len_cls_nm) + len_cls_sha1_x: char* = self.Gen.StructGen.get_struct_sha1(len_cls_nm) if len_cls_sha1_x is not None: # Buffer must fit "{sha1}.{cls}.__len__": 2 dots + "__len__"(7) + NUL = 10; # +8 truncates the last two chars and breaks the link. len_ml_x: sizet = string.strlen(len_cls_sha1_x) + string.strlen(len_cls_nm) + 10 - len_mangled_x: str = pool.alloc(len_ml_x) + len_mangled_x: char* = pool.alloc(len_ml_x) if len_mangled_x is not None: viperlib.snprintf(len_mangled_x, len_ml_x, "%s.%s.__len__", len_cls_sha1_x, len_cls_nm) len_ret_x: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, len_cls_sha1_x, len_cls_nm, "__len__") @@ -734,7 +734,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # fail-fast: the class has no __len__ (compile-time error, matching TPC # HandlesExprBuiltin._FailFastLenUnsupported wording). self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.ArrayT[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError") - # Non-struct: str (Ptr(Int8)) uses strlen; other types fail fast + # Non-struct: char* (Ptr(Int8)) uses strlen; other types fail fast len_arg_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(len_val) len_is_str: int = 0 if len_arg_ty is not None and self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0: @@ -778,7 +778,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return None - def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: + def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: """Static class/method/receiver/self.field/list built-ins; sets hit_box, else returns None.""" # REnum.kind() compiles to a __tag read (offset 0, type from the field declaration): bitcast obj # to __tag* + load. Four criteria detect REnum, incl. pointee __tag and X.field annotations. @@ -789,7 +789,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if rk_obj is not None and rk_obj.Ty is not None: rk_ty: mlirlite.LLVMType* = rk_obj.Ty rk_load: int = 0 - rk_cls: str = None + rk_cls: char* = None rk_pointee: mlirlite.LLVMType* = None # rk_is_rn: whether already determined to be a REnum, decoupled from rk_cls. rk_is_rn: int = 0 @@ -820,17 +820,17 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_nm: ast.Name* = ast.Name*(rk_at.value) if rk_nm.id is not None: rk_ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_nm.id) - rk_annot_raw: str = self.Gen.VarGen.var_annot_class_name(rk_ve) + rk_annot_raw: char* = self.Gen.VarGen.var_annot_class_name(rk_ve) if rk_annot_raw is not None: # Truncate the union/generic suffix (" | rawptr" / "[...]") rk_ae: sizet = 0 while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': rk_ae += 1 - rk_ab: str = pool.alloc(rk_ae + 1) + rk_ab: char* = pool.alloc(rk_ae + 1) if rk_ab is not None: string.strncpy(rk_ab, rk_annot_raw, rk_ae) rk_ab[rk_ae] = '\0' # Strip the module prefix ("mlirlite.LLVMType" -> "LLVMType") - rk_ad: str = string.strrchr(rk_ab, '.') + rk_ad: char* = string.strrchr(rk_ab, '.') if rk_ad is not None and rk_ad[1] != '\0': rk_cls = rk_ad + 1 else: rk_cls = rk_ab # Same criteria as above (table or struct with __tag), not just the variant table @@ -850,17 +850,17 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_bnm: ast.Name* = ast.Name*(rk_bat.value) if rk_bnm.id is not None: rk_bve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_bnm.id) - rk_bannot: str = self.Gen.VarGen.var_annot_class_name(rk_bve) + rk_bannot: char* = self.Gen.VarGen.var_annot_class_name(rk_bve) if rk_bannot is not None: rk_blen: sizet = 0 while rk_bannot[rk_blen] != '\0' and rk_bannot[rk_blen] != ' ' and rk_bannot[rk_blen] != '|' and rk_bannot[rk_blen] != '[': rk_blen += 1 - rk_bbuf: str = pool.alloc(rk_blen + 1) + rk_bbuf: char* = pool.alloc(rk_blen + 1) if rk_bbuf is not None: string.strncpy(rk_bbuf, rk_bannot, rk_blen) rk_bbuf[rk_blen] = '\0' # Strip the module prefix ("mlirlite.Value" -> "Value") - rk_bdot: str = string.strrchr(rk_bbuf, '.') - rk_bcls: str = rk_bbuf + rk_bdot: char* = string.strrchr(rk_bbuf, '.') + rk_bcls: char* = rk_bbuf if rk_bdot is not None and rk_bdot[1] != '\0': rk_bcls = rk_bdot + 1 rk_bst: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(rk_bcls) if rk_bst is not None: @@ -871,7 +871,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_fpt = rk_fpt.Pointee if rk_fpt is not None and self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0: rk_fpt = rk_fpt.Pointee if rk_fpt is not None: - rk_fcls: str = self.Gen.StructGen.get_class_name_by_type(pool, rk_fpt) + rk_fcls: char* = self.Gen.StructGen.get_class_name_by_type(pool, rk_fpt) if rk_fcls is not None: if self.Gen.ClassGenEnum._is_renum_class_name(rk_fcls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_fcls) != 0: rk_is_rn = 1 @@ -954,7 +954,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # The struct value is inline in the slot: the slot address is the object address (self) rp_val = self.Gen.VarGen.repl_try_addr(trans, rp_nm.id, cl) else: rp_val = self.Gen.VarGen.repl_try_read(trans, rp_nm.id, cl) - rp_cls: str = None + rp_cls: char* = None if rp_val is not None and rp_val.Ty is not None: rp_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(rp_val) if rp_sty is not None: rp_cls = self.Gen.StructGen.get_class_name_by_type(pool, rp_sty) @@ -983,7 +983,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): recv_ty_c = recv_ty_c.Pointee # Heap objects (@t.Object) are double pointers: deref once more to get the struct if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0: recv_ty_c = recv_ty_c.Pointee - recv_cls_c: str = self.Gen.StructGen.get_class_name_by_type(pool, recv_ty_c) + recv_cls_c: char* = self.Gen.StructGen.get_class_name_by_type(pool, recv_ty_c) if recv_cls_c is not None: if self.Gen.CallGenProp._is_list_builtin_receiver(pool, recv_val_c, recv_cls_c, method_at.attr, cl) == 0: obj_ptr_c: mlirlite.Value* = recv_val_c @@ -1014,7 +1014,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if nl_slot is not None: nl_deref = nl_slot nl_struct: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(nl_deref) if nl_struct is not None: - nl_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, nl_struct) + nl_cls: char* = self.Gen.StructGen.get_class_name_by_type(pool, nl_struct) if nl_cls is not None: if self.Gen.CallGenProp._is_list_builtin_receiver(pool, nl_deref, nl_cls, func_name, cl) == 0: if hit_box is not None: hit_box[0] = 1 @@ -1028,15 +1028,15 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Identify list generic container annotations early (shared by the class branches below): rawptr[list[rawptr[AST]]] is Ptr(Ptr(Struct('list[...]'))), and the list specialty struct is not registered as a normal class, so unwrap one rawptr and flag is_list_annot_builtin for the inlined list branch. var_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, method_obj_nm.id) is_list_annot_builtin: int = 0 - la_buf: str = self.Gen.VarGen.var_annot_class_name(var_entry) + la_buf: char* = self.Gen.VarGen.var_annot_class_name(var_entry) if la_buf is not None: - la_tail: str = la_buf + la_tail: char* = la_buf if string.strncmp(la_buf, "rawptr[", 7) == 0: la_tail = la_buf + 7 if string.strncmp(la_tail, "list", 4) == 0: if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, la_tail, func_name, cl) != 0: is_list_annot_builtin = 1 match obj_var.Ty: case mlirlite.LLVMType.Ptr(obj_struct_ty): - class_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty) + class_nm: char* = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty) if class_nm is not None: # list builtin container methods (append/get/set/pop/clear/__iter__/...) are # inlined by the list builtin branch below; skip _translate_method_call for them. @@ -1047,7 +1047,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Ptr(Struct) before lookup. match obj_struct_ty: case mlirlite.LLVMType.Ptr(inner_struct_ty): - inner_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, inner_struct_ty) + inner_nm: char* = self.Gen.StructGen.get_class_name_by_type(pool, inner_struct_ty) if inner_nm is not None: # Skip list builtin methods here too (same as the Ptr(Struct) branch); # inner_nm may also be misread as the inner element class. @@ -1063,12 +1063,12 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if fd_name_res is not None: return fd_name_res # AnnotClassName fallback: for unions simplified to Ptr(i8), look up the struct by the # original annotation's class name. Skip when is_list_annot_builtin is set. - annot_val: str = self.Gen.VarGen.var_annot_class_name(var_entry) + annot_val: char* = self.Gen.VarGen.var_annot_class_name(var_entry) if annot_val is not None and is_list_annot_builtin == 0: # Parse the module-qualified name "memhub.MemBuddy" -> mod_nm="memhub", cls_nm="MemBuddy" - dot_ptr: str = string.strrchr(annot_val, '.') - cls_nm2: str = annot_val - mod_nm2: str = None + dot_ptr: char* = string.strrchr(annot_val, '.') + cls_nm2: char* = annot_val + mod_nm2: char* = None if dot_ptr is not None: cls_nm2 = dot_ptr + 1 total_len_av: sizet = string.strlen(annot_val) @@ -1099,12 +1099,12 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if fd_res is not None: return fd_res # Struct unregistered (cross-module dependency not translated): look up # the module SHA1 to build the method call name. - sha1_fc: str = None + sha1_fc: char* = None if mod_nm2 is not None: sha1_fc = self._lookup_module_sha1(mod_nm2) if sha1_fc is not None: # Build the "{sha1}.{cls_nm2}.{func_name}" call name mlen3: sizet = string.strlen(sha1_fc) + string.strlen(cls_nm2) + string.strlen(func_name) + 3 - mangled3: str = pool.alloc(mlen3) + mangled3: char* = pool.alloc(mlen3) if mangled3 is not None: viperlib.snprintf(mangled3, mlen3, "%s.%s.%s", sha1_fc, cls_nm2, func_name) # load obj_ptr (self) @@ -1161,7 +1161,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): expr_root: ast.AST* = expr_method_at.value while expr_root is not None and expr_root.kind() == ast.ASTKind.Attribute: expr_root = ast.Attribute*(expr_root).value if expr_root is not None and expr_root.kind() == ast.ASTKind.Name: - expr_root_nm: str = ast.Name*(expr_root).id + expr_root_nm: char* = ast.Name*(expr_root).id if expr_root_nm is not None: if trans._imported_modules is not None: if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, expr_root_nm) != 0: is_mod_path_expr = 1 @@ -1169,7 +1169,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Translate the receiver expression (the result should be Ptr(Struct)) expr_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, expr_method_at.value, funcs_ptr, func_count, trans) if expr_obj is not None and expr_obj.Ty is not None: - expr_cls_nm: str = None + expr_cls_nm: char* = None # Recursively unwrap Ptr to handle the Ptr(Ptr(Struct)) of X* unions (e.g. Vec3**); # otherwise the method call is treated as a bare @dot and links undefined. expr_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(expr_obj) @@ -1212,7 +1212,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Translate self.__pool__ to get the field value (an already-loaded object pointer) field_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, attr_method_at.value, funcs_ptr, func_count, trans) if field_obj is not None and field_obj.Ty is not None: - field_cls_nm: str = None + field_cls_nm: char* = None # Path 1: get the class name from the field value's LLVM type match field_obj.Ty: case mlirlite.LLVMType.Ptr(field_struct_ty): @@ -1228,9 +1228,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): case mlirlite.LLVMType.Ptr(field_owner_struct_ty): field_info: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(field_owner_struct_ty, inner_attr.attr) if field_info is not None: - field_annot: str = self.Gen.StructGen.get_field_annot_class_name(field_info) + field_annot: char* = self.Gen.StructGen.get_field_annot_class_name(field_info) if field_annot is not None: - dot_p: str = string.strrchr(field_annot, 46) + dot_p: char* = string.strrchr(field_annot, 46) if dot_p is not None: field_cls_nm = dot_p + 1 else: field_cls_nm = field_annot if field_cls_nm is not None: @@ -1253,7 +1253,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: lm_at: ast.Attribute* = ast.Attribute*(cl.func) if lm_at is not None and lm_at.attr is not None and lm_at.value is not None: - lm_name: str = lm_at.attr + lm_name: char* = lm_at.attr # Check whether this is a list method name lm_is_list: int = 0 if string.strcmp(lm_name, "get") == 0: lm_is_list = 1 @@ -1278,7 +1278,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Confirm the object really is a list (the branch matches by method name only, and # get/set are not list-specific); skip otherwise to avoid wrong GEP offsets. lm_conf_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) - lm_conf_nm: str = None + lm_conf_nm: char* = None if lm_conf_ty is not None: lm_conf_nm = mlirlite.get_struct_name(lm_conf_ty) # [S4] Compare the container base name exactly: the LLVM name carries a module sha1 # prefix; SpecTypeNameBaseIs strips/truncates before comparing, avoiding substring false hits. @@ -1292,7 +1292,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Element type T is resolved from the list specialization name (list[int]->i32, # list[str]->i8*); using a fixed i8* would corrupt adjacent elements in set/pop. lm_esty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) - lm_ename: str = None + lm_ename: char* = None if lm_esty is not None: lm_ename = mlirlite.get_struct_name(lm_esty) lm_elem_ty: mlirlite.LLVMType* = None if lm_ename is not None: lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) @@ -1382,7 +1382,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # memory reallocation handled in the _list implementation. elif string.strcmp(lm_name, "append") == 0: if can >= 1: - ap_sha1: str = self._lookup_module_sha1("_list") + ap_sha1: char* = self._lookup_module_sha1("_list") if ap_sha1 is None: # Dependency module not compiled (_list not in the chain): fail fast, never # silently skip append (elements would never be added). @@ -1390,22 +1390,22 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if ap_sha1 is not None: # The append symbol is {sha1}.list[AST*].append (specialized name), not # {sha1}.list.append; derive the specialized name from lm_obj's type. - ap_spec_nm: str = None + ap_spec_nm: char* = None ap_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) if ap_struct_ty is not None: ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) if ap_spec_nm is None: ap_spec_nm = "list" # Trigger generic specialization translation (idempotent): the append define is # emitted when the specialty class is translated, otherwise the symbol is missing. if trans is not None and ap_spec_nm is not None: - lbkt_ap: str = string.strchr(ap_spec_nm, '[') + lbkt_ap: char* = string.strchr(ap_spec_nm, '[') if lbkt_ap is not None: - rbkt_ap: str = string.strrchr(ap_spec_nm, ']') + rbkt_ap: char* = string.strrchr(ap_spec_nm, ']') if rbkt_ap is not None and rbkt_ap > lbkt_ap: base_len_ap: sizet = sizet(uint64(lbkt_ap) - uint64(ap_spec_nm)) arg_len_ap: sizet = sizet(uint64(rbkt_ap) - uint64(lbkt_ap) - 1) if base_len_ap > 0 and arg_len_ap > 0: - base_buf_ap: str = pool.alloc(base_len_ap + 1) - arg_buf_ap: str = pool.alloc(arg_len_ap + 1) + base_buf_ap: char* = pool.alloc(base_len_ap + 1) + arg_buf_ap: char* = pool.alloc(arg_len_ap + 1) if base_buf_ap is not None and arg_buf_ap is not None: string.strncpy(base_buf_ap, ap_spec_nm, base_len_ap) base_buf_ap[base_len_ap] = '\0' @@ -1414,14 +1414,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): args_ap: list[str]* = list[str](pool, 8) if args_ap is not None: # Comma-separated multiple type args (list[X] / dict[K, V]) - cur_ap: str = arg_buf_ap + cur_ap: char* = arg_buf_ap while cur_ap is not None: - comma_ap: str = string.strchr(cur_ap, ',') + comma_ap: char* = string.strchr(cur_ap, ',') if comma_ap is None: args_ap.append(cur_ap) break seg_len_ap: sizet = sizet(uint64(comma_ap) - uint64(cur_ap)) - seg_buf_ap: str = pool.alloc(seg_len_ap + 1) + seg_buf_ap: char* = pool.alloc(seg_len_ap + 1) if seg_buf_ap is not None: string.strncpy(seg_buf_ap, cur_ap, seg_len_ap) seg_buf_ap[seg_len_ap] = '\0' @@ -1431,7 +1431,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # Call name "{sha1}.{spec}.append": length is spec + 25 (16+1+7+1), so the old +8 # truncated the trailing 'd' and produced an undefined symbol. ap_mlen: sizet = string.strlen(ap_sha1) + string.strlen(ap_spec_nm) + 26 - ap_mangled: str = pool.alloc(ap_mlen) + ap_mangled: char* = pool.alloc(ap_mlen) if ap_mangled is not None: viperlib.snprintf(ap_mangled, ap_mlen, "%s.%s.append", ap_sha1, ap_spec_nm) ap_item_node: ast.AST* = cargs.get(0) diff --git a/App/lib/core/Gen/Call/CallGenFd.vp b/App/lib/core/Gen/Call/CallGenFd.vp index 7b46c99..9608e81 100644 --- a/App/lib/core/Gen/Call/CallGenFd.vp +++ b/App/lib/core/Gen/Call/CallGenFd.vp @@ -14,7 +14,7 @@ from . import CallGenBase # CallGenFd - split from CallGenMixin (stage B): FakeDuck / requires field injection / provider stack novirtual class CallGenFd(CallGenBase.CallGenBase): """FakeDuck / requires field injection / provider stack""" - def _translate_fakeduck_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: str, method_name: str, cl: ast.Call*, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_fakeduck_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: char*, method_name: char*, cl: ast.Call*, trans: HT.Translator*) -> mlirlite.Value*: """FakeDuck: resolve a str variable's method call to extension class _Type/_str, return the call result or None""" if pool is None or builder is None or cl is None or trans is None: return None if method_name is None: return None @@ -27,11 +27,11 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): if string.strcmp(fd_at.attr, method_name) != 0: return None # Candidate extension classes: _Type first (a.type_id()), then _str (a.upper() etc.) fd_func: mlirlite.Function* = None - fd_cls: str = None - fd_key: str = pool.alloc(160) + fd_cls: char* = None + fd_key: char* = pool.alloc(160) if fd_key is not None: for fd_ci in range(2): - fd_cn: str = "_Type" + fd_cn: char* = "_Type" if fd_ci == 1: fd_cn = "_str" viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name) fd_func = self.find_func_in_module(mod, fd_key) @@ -53,7 +53,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): fd_onm: ast.Name* = ast.Name*(fd_at.value) if fd_onm.id is not None: # Pool-persistent buffer (an f-string stack buffer would expire after return) - fd_mn: str = pool.alloc(256) + fd_mn: char* = pool.alloc(256) if fd_mn is not None: viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id) fd_meta: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_mn) if fd_meta is not None and fd_has_fields != 0: fd_self = fd_meta @@ -99,7 +99,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): if fd_arg.kind() == ast.ASTKind.Constant: fd_ac: ast.Constant* = ast.Constant*(fd_arg) if fd_ac.const_kind == ast.CONST_CHAR: - ch_buf: str = pool.alloc(2) + ch_buf: char* = pool.alloc(2) if ch_buf is not None: ch_buf[0] = char(fd_ac.int_val) ch_buf[1] = '\0' @@ -111,11 +111,11 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # Return type and call name (from the function definition hit by find_func_in_module) fd_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fd_func) if fd_ret_ty is None: fd_ret_ty = mlirlite.Int32(pool) - fd_fname: str = mlirlite.function_get_name(fd_func) + fd_fname: char* = mlirlite.function_get_name(fd_func) if fd_fname is None: return None # Refine return type: cross-module declare may simplify a list[T] specialization return type to Ptr(i8), degrading the caller's alloca type -> parts[0] takes the char-index path instead of list inline __getitem__ (printf %s crash). Authority is the defining module's vpi (fallback text.ll); extract the module sha1 only when the name is "{16hex}.{func}" (via GenApi.sha1_prefix_len) if GenApi.sha1_prefix_len(fd_fname) != 0: - fd_sha1: str = pool.alloc(17) + fd_sha1: char* = pool.alloc(17) if fd_sha1 is not None: string.strncpy(fd_sha1, fd_fname, 16) fd_sha1[16] = '\0' @@ -131,7 +131,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # For each class __requires__ field (registered by fd1), call _find_provider(field) at runtime; if non-NULL bitcast and store it (conditional inject); skip when _find_provider is unregistered. # ============================================================ - def _inject_requires_fields(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, meta_ptr: mlirlite.Value*, class_name: str) -> int: + def _inject_requires_fields(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, meta_ptr: mlirlite.Value*, class_name: char*) -> int: """Inject requires fields from the with context, return the injected field count""" if trans is None or pool is None or builder is None or mod is None: return 0 if meta_ptr is None or class_name is None: return 0 @@ -139,7 +139,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # (matches TPC L4048-4050); otherwise non-with projects would emit undefined {sha1}._find_provider calls. fd_fn_probe: mlirlite.Function* = self.find_func_in_module(mod, "_find_provider") if fd_fn_probe is None: return 0 - fd_fname: str = mlirlite.function_get_name(fd_fn_probe) + fd_fname: char* = mlirlite.function_get_name(fd_fn_probe) if fd_fname is None: return 0 cnt: int = self.Gen.ClassGenBase.class_meta_count(GenTypes.CLASS_META_REQUIRES, class_name) if cnt <= 0: return 0 @@ -153,7 +153,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): if cur_func is None: return 0 injected: int = 0 for ji in range(int(cnt)): - fname: str = self.Gen.ClassGenBase.class_meta_field_at(GenTypes.CLASS_META_REQUIRES, class_name, ji) + fname: char* = self.Gen.ClassGenBase.class_meta_field_at(GenTypes.CLASS_META_REQUIRES, class_name, ji) if fname is None: continue fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(sty, fname) if fe is None or fe.Ty is None: continue @@ -173,7 +173,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # conflict -> llc "Terminator found in the middle of a basic block"). vtc2: int = trans._label_counter trans._label_counter = vtc2 + 1 - fd_bb_buf2: str = pool.alloc(64) + fd_bb_buf2: char* = pool.alloc(64) if fd_bb_buf2 is None: continue viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2) fd_skip_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, cur_func, fd_bb_buf2) @@ -196,7 +196,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # Matches TPC HandlesWith.py L138-174: push _push_provider(field, ctx_i8) on entry and equal _pop_provider() on exit. # ============================================================ - def _emit_provider_push(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: str, ctx_val: mlirlite.Value*) -> int: + def _emit_provider_push(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: char*, ctx_val: mlirlite.Value*) -> int: """Emit a _push_provider(field, ctx_i8) call per provided field, return the field count""" if trans is None or pool is None or builder is None or mod is None: return 0 if cls_name is None or ctx_val is None: return 0 @@ -206,7 +206,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # skip when this module does not import _withcontent, to avoid undefined symbol). fd_pfn_probe: mlirlite.Function* = self.find_func_in_module(mod, "_push_provider") if fd_pfn_probe is None: return 0 - fd_pfn: str = mlirlite.function_get_name(fd_pfn_probe) + fd_pfn: char* = mlirlite.function_get_name(fd_pfn_probe) if fd_pfn is None: return 0 i8_ty_p: mlirlite.LLVMType* = mlirlite.Int8(pool) if i8_ty_p is None: return 0 @@ -218,7 +218,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): fd_ctx_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ctx_val, i8_ptr_ty_p) if fd_ctx_i8 is None: return 0 for pi in range(int(fd_pc)): - fname: str = self.Gen.ClassGenBase.class_meta_field_at(GenTypes.CLASS_META_PROVIDES, cls_name, pi) + fname: char* = self.Gen.ClassGenBase.class_meta_field_at(GenTypes.CLASS_META_PROVIDES, cls_name, pi) if fname is None: continue fd_fstr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fname, trans) if fd_fstr is None: continue @@ -227,7 +227,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): self._ensure_method_declare(pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2) mlirlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0) return fd_pc - def _emit_provider_pop(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: str) -> int: + def _emit_provider_pop(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cls_name: char*) -> int: """Emit a _pop_provider() call per provided field, return the field count""" if trans is None or pool is None or builder is None or mod is None: return 0 if cls_name is None: return 0 @@ -237,7 +237,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # skip when this module does not import _withcontent, to avoid undefined symbol). fd_pon_probe: mlirlite.Function* = self.find_func_in_module(mod, "_pop_provider") if fd_pon_probe is None: return 0 - fd_pon: str = mlirlite.function_get_name(fd_pon_probe) + fd_pon: char* = mlirlite.function_get_name(fd_pon_probe) if fd_pon is None: return 0 ret_i32_q: mlirlite.LLVMType* = mlirlite.Int32(pool) if ret_i32_q is None: return 0 diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 572b1f6..caa4c4c 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -17,7 +17,7 @@ from . import CallGenBase novirtual class CallGenLib(CallGenBase.CallGenBase): """C-lib declarations / return-type inference / kwargs call helpers (extends Base)""" - def _ensure_c_lib_declare(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, name: str) -> mlirlite.Function*: + def _ensure_c_lib_declare(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, name: char*) -> mlirlite.Function*: """Create a declare for a known C-lib function""" if pool is None or mod is None or name is None: return None @@ -94,7 +94,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): mlirlite.add_param(pool, fn, i64_ty, "n") return fn - def _promote_clib_call_args(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, call_name: str, head: mlirlite.Value*, count: int) -> mlirlite.Value*: + def _promote_clib_call_args(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, call_name: char*, head: mlirlite.Value*, count: int) -> mlirlite.Value*: """Promote bare-name C-lib call arguments to their standard signature widths""" if pool is None or builder is None or call_name is None or head is None: return head # bare names only (no '.' -> no sha1 prefix); prefixed ones use vpi definition-side parsing @@ -148,16 +148,16 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # _coerce_args_to_def_params: coerce cross-module call args to vpi definition-side param # types so call/declare/define widths match; bare C-lib names use the C-lib path instead. - def _coerce_args_to_def_params(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, call_name: str, head: mlirlite.Value*, count: int, cargs: list[ast.AST*]* = None, self_off: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*: + def _coerce_args_to_def_params(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, call_name: char*, head: mlirlite.Value*, count: int, cargs: list[ast.AST*]* = None, self_off: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*: """Coerce cross-module call args to vpi definition-side param types; returns the rebuilt chain""" if pool is None or builder is None or call_name is None or head is None: return head if self._is_sha1_mangled_call(call_name) == 0: return head # split {sha1}.{rest}: if rest has '.', it is {cls}.{method}, else {func} - rest: str = call_name + 17 - cls_nm: str = None - meth_nm: str = rest + rest: char* = call_name + 17 + cls_nm: char* = None + meth_nm: char* = rest # take the last '.': the method has none, and the first '.' would truncate qualified type args - dot_r: str = string.strrchr(rest, 46) + dot_r: char* = string.strrchr(rest, 46) if dot_r is not None: cls_len: sizet = uint64(dot_r) - uint64(rest) if cls_len <= 0: return head @@ -178,7 +178,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): sha1_buf[16] = '\0' # ensure-load + direct cache lookup (not _vpi_method_param_annot, which misses module funcs) if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_param_annot_loaded(sha1_buf, self.Gen.CallGenBase.TempDir) - prm_annots: str = VpiReader._lookup_vpi_param_annots(sha1_buf, cls_nm, meth_nm) + prm_annots: char* = VpiReader._lookup_vpi_param_annots(sha1_buf, cls_nm, meth_nm) # generic-specialized class: annotations live on the template class, so fall back to template lookup tpl_src: int = 0 if prm_annots is None: @@ -206,7 +206,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # Value-reference params (&T / &temp T): auto-address the argument (cross-module callee). # The mode comes from the definition-side vpi annotation segment (shared resolver); if the # arg is not a pointer it is addressed (ref: lvalue) or copied into a temp slot (temp). - vpi_cur_sha: str = None + vpi_cur_sha: char* = None if trans is not None: vpi_cur_sha = trans.ModuleSha1 mode_cm: int = self.Gen.CallGenBase._vpi_auto_addr_mode(call_name, vpi_cur_sha, idx) if mode_cm != 0 and trans is not None and trans.Module is not None: @@ -291,14 +291,14 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): pass return val - def _infer_external_func_ret_ty(self, pool: memhub.MemBuddy*, func_name: str, node: ast.AST*, fatal_if_unknown: int) -> mlirlite.LLVMType*: + def _infer_external_func_ret_ty(self, pool: memhub.MemBuddy*, func_name: char*, node: ast.AST*, fatal_if_unknown: int) -> mlirlite.LLVMType*: """Infer the return type of an external includes function; a whitelist miss may fail fast""" if pool is None or func_name is None: return mlirlite.Int32(pool) # extract the bare function name by stripping the SHA1 prefix # (16 hex digits + '.'), e.g. "240a9a4157959a9f.parse" -> "parse". - bare_name: str = func_name - dot_pos: str = string.strrchr(func_name, 46) # 46 = ord('.') + bare_name: char* = func_name + dot_pos: char* = string.strrchr(func_name, 46) # 46 = ord('.') if dot_pos is not None: # the part after '.' is the bare function name bare_name = dot_pos + 1 @@ -396,7 +396,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # Default i32 placeholder: fatal_if_unknown=1 fails fast; =0 (Phase A mid-pass) stays silent. if fatal_if_unknown != 0: self.Gen.TypeGenErr.fatal_error(node, f"external function return type is unregistered and cannot be inferred conclusively (defaulting to i32 would truncate pointers/i64; provide a stub declaration or add it to the whitelist): {func_name}", "TypeError") return mlirlite.Int32(pool) - def _get_external_func_param_ty(self, pool: memhub.MemBuddy*, func_name: str, param_idx: int) -> mlirlite.LLVMType*: + def _get_external_func_param_ty(self, pool: memhub.MemBuddy*, func_name: char*, param_idx: int) -> mlirlite.LLVMType*: """Return the expected type of an external function's param_idx-th parameter, or None (fallback only)""" if pool is None or func_name is None: return None @@ -409,7 +409,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # list iteration is unsupported; use range + get instead api_count: sizet = len(win32_apis) for ai in range(int(api_count)): - api_name: str = win32_apis.get(ai) + api_name: char* = win32_apis.get(ai) if string.strcmp(api_name, func_name) == 0: return i64_ty # Allocators: size params are declared i64 (size_t); without promotion on bare-name fallback call/define widths mismatch; calloc/realloc size is idx 1 @@ -421,7 +421,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): if param_idx == 1: return i64_ty return None - def _is_sha1_mangled_call(self, call_name: str) -> int: + def _is_sha1_mangled_call(self, call_name: char*) -> int: """Return whether call_name is a cross-module Viper function ("{16 hex}.func")""" if call_name is None: return 0 if GenApi.sha1_prefix_len(call_name) != 0: return 1 @@ -498,7 +498,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # _translate_call_with_kwargs: keyword-arg call; builds args in found_func.Params order (positional first, else match by param name) # ============================================================ - def _translate_call_with_kwargs(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, func_name: str, found_func: mlirlite.Function*, cargs: list[ast.AST*]*, can: sizet, keywords: list[ast.AST*]*, kw_count: sizet, trans: HT.Translator*) -> mlirlite.Value*: + def _translate_call_with_kwargs(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, func_name: char*, found_func: mlirlite.Function*, cargs: list[ast.AST*]*, can: sizet, keywords: list[ast.AST*]*, kw_count: sizet, trans: HT.Translator*) -> mlirlite.Value*: """Translate a call with keyword arguments, building args in parameter order""" head: mlirlite.Value* = None tail: mlirlite.Value* = None @@ -510,11 +510,11 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # Default-arg lookup for omitted params (same source as CallGenMixin non-kwargs path): # module SHA1 is the "{sha1}.func" prefix or current module; the name+SHA1-keyed snapshot survives resets. - kw_callee_sha: str = None - kw_found_name: str = mlirlite.function_get_name(found_func) + kw_callee_sha: char* = None + kw_found_name: char* = mlirlite.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) + kw_sha_buf: char* = pool.alloc(17) if kw_sha_buf is not None: string.strncpy(kw_sha_buf, kw_found_name, 16) kw_sha_buf[16] = '\0' @@ -544,7 +544,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, param_ty) else: # Find the matching keyword argument - param_name: str = mlirlite.param_get_name(cur_param) + param_name: char* = mlirlite.param_get_name(cur_param) if param_name is not None: for ki in range(int(kw_count)): kw: ast.Keyword* = ast.Keyword*(keywords.get(ki)) @@ -582,8 +582,8 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): cur_param = mlirlite.param_get_next(cur_param) # declare and define both use found_func.Name: normal funcs carry the SHA1 prefix, t.ExternT/t.State/t.ExportT use bare names (bare names desync call/define symbols) - call_name: str = func_name - found_name: str = mlirlite.function_get_name(found_func) + call_name: char* = func_name + found_name: char* = mlirlite.function_get_name(found_func) if found_name is not None: call_name = found_name # Return type (via accessor) diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index c7bc3b2..fcc47f6 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -44,14 +44,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if self.Gen.CallGenBase.StaticCount <= 0: return 0 sc_at: ast.Attribute* = ast.Attribute*(cl.func) if sc_at.value is None or sc_at.attr is None: return 0 - sc_mod: str = None + sc_mod: char* = None if sc_at.value.kind() == ast.ASTKind.Name: sc_nm: ast.Name* = ast.Name*(sc_at.value) sc_mod = sc_nm.id elif sc_at.value.kind() == ast.ASTKind.Attribute: sc_mod = self.Gen.ExprGenAttr._attr_module_path_str(pool, sc_at.value) if sc_mod is None: return 0 if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, sc_mod) == 0: return 0 - sc_sha1: str = self.Gen.StructGen._resolve_module_sha1(sc_mod, trans._from_imports) + sc_sha1: char* = self.Gen.StructGen._resolve_module_sha1(sc_mod, trans._from_imports) if sc_sha1 is None: return 0 if string.strncmp(sc_sha1, trans.ModuleSha1, 16) == 0: return 0 if self.Gen.CallGenBase.IsStaticSymbol(sc_sha1, sc_at.attr) == 0: return 0 @@ -130,7 +130,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if param_idx < can: if cargs is not None: arg_node_kw = cargs.get(param_idx) else: - pname_kw: str = mlirlite.param_get_name(cur_param) + pname_kw: char* = mlirlite.param_get_name(cur_param) if pname_kw is not None and keywords is not None: ki_kw: sizet for ki_kw in range(int(kw_count)): @@ -149,7 +149,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # _defaults_entry_from_vpi - 全局表里没有该函数的缺省值时,直接按定义模块 .vpi 签名临时造一条 # 快照条目(kinds/ints/strs 由文本解析得到,字符串已深拷贝进 PermPool),仅本次调用使用。 - def _defaults_entry_from_vpi(self, pool: memhub.MemBuddy*, sha1: str, name: str) -> GenTypes.FuncDefaultsEntry*: + def _defaults_entry_from_vpi(self, pool: memhub.MemBuddy*, sha1: char*, name: char*) -> GenTypes.FuncDefaultsEntry*: """按 .vpi 签名临时构造缺省值条目;无缺省值或不可重建返回 None""" cap: int = 128 # 快照数组放 PermPool:条目可能在后续 pool reset 之后才被消费,放 pool 会悬空。 @@ -179,15 +179,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 早期补参用的是 dfx_callee_sha,链式接收者(`self.Gen.X.m(...)`)解析不出发起模块时它会 # 退化成调用方 SHA1,表查不到;此时 call_name 已带定义模块 SHA1 前缀,是权威键,再补一次。 # 返回补齐后的实参个数。 - def _fill_defaults_late(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, builder: mlirlite.IRBuilder*, trans: HT.Translator*, cl: ast.Call*, call_name: str, head: mlirlite.Value*, can: sizet) -> sizet: + def _fill_defaults_late(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, builder: mlirlite.IRBuilder*, trans: HT.Translator*, cl: ast.Call*, call_name: char*, head: mlirlite.Value*, can: sizet) -> sizet: """按 call_name 里的定义模块 SHA1 前缀补缺省参数;返回新的实参个数""" if head is None or can == 0 or call_name is None: return can if self.Gen.CallGenLib._is_sha1_mangled_call(call_name) == 0: return can - sh_buf: str = pool.alloc(17) + sh_buf: char* = pool.alloc(17) if sh_buf is None: return can string.strncpy(sh_buf, call_name, 16) sh_buf[16] = '\0' - cname: str = call_name + 17 + cname: char* = call_name + 17 if cname[0] == '\0': return can # 只做 SHA1 隔离的查找:表按 (名字, 定义模块 SHA1) 定位;表里没有就直接读该模块的 .vpi。 # 绝不按裸名跨模块搜(`run` 这类名字在多个模块里都有,会拿错签名去补参/校验)。 @@ -263,7 +263,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): self._CheckStaticCallCrossModule(pool, trans, cl) if cl is None: return None - func_name: str = self.Gen.ExprGenBase.get_func_name(cl.func) + func_name: char* = self.Gen.ExprGenBase.get_func_name(cl.func) cargs: list[ast.AST*]* = cl.args can: sizet = 0 @@ -291,19 +291,19 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 走下面的跨模块回退时置 0 —— 跨模块的掩码是合并值,不能再按"字段位"裁剪(会变成漏报)。 loc_mask: int = 1 # 跨模块回退解析出的被调者模块 sha1(最终裁决要用它去查对方 .vpi 的指令契约) - mod_sha_ec: str = None + mod_sha_ec: char* = None if esc_mask == 0: loc_mask = 0 if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_ec: ast.Attribute* = ast.Attribute*(cl.func) - mod_p_ec: str = None + mod_p_ec: char* = None if at_ec.value is not None and at_ec.value.kind() == ast.ASTKind.Name: mn_ec: ast.Name* = ast.Name*(at_ec.value) if mn_ec.id is not None: mod_p_ec = mn_ec.id elif at_ec.value is not None and at_ec.value.kind() == ast.ASTKind.Attribute: mod_p_ec = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_ec.value) if mod_p_ec is not None: - fi_ec: str = None + fi_ec: char* = None if trans is not None: fi_ec = trans._from_imports mod_sha_ec = self.Gen.StructGen._resolve_module_sha1(mod_p_ec, fi_ec) if mod_sha_ec is None and trans is not None and trans._from_imports is not None: @@ -353,17 +353,17 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if cargs is not None and func_name is not None: wf_mask = GenApi.get_param_willfree(func_name) if wf_mask == 0: - mod_sha_wf: str = None + mod_sha_wf: char* = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_wf: ast.Attribute* = ast.Attribute*(cl.func) - mod_p_wf: str = None + mod_p_wf: char* = None if at_wf.value is not None and at_wf.value.kind() == ast.ASTKind.Name: mn_wf: ast.Name* = ast.Name*(at_wf.value) if mn_wf.id is not None: mod_p_wf = mn_wf.id elif at_wf.value is not None and at_wf.value.kind() == ast.ASTKind.Attribute: mod_p_wf = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_wf.value) if mod_p_wf is not None: - fi_wf: str = None + fi_wf: char* = None if trans is not None: fi_wf = trans._from_imports mod_sha_wf = self.Gen.StructGen._resolve_module_sha1(mod_p_wf, fi_wf) if mod_sha_wf is None and trans is not None and trans._from_imports is not None: @@ -402,7 +402,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): sub_node: ast.Subscript* = ast.Subscript*(cl.func) if sub_node.value is not None and sub_node.value.kind() == ast.ASTKind.Name: gen_nm_node: ast.Name* = ast.Name*(sub_node.value) - gen_class_name: str = gen_nm_node.id + gen_class_name: char* = gen_nm_node.id # Check whether this is a generic class template. template_cd: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(gen_class_name) if template_cd is not None: @@ -410,7 +410,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): gen_type_args: list[str]* = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, sub_node.slice, trans._from_imports) if gen_type_args is not None and len(gen_type_args) > 0: # Specialize the generic class and return the specialized name. - spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_class_name, gen_type_args) + spec_name: char* = self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_class_name, gen_type_args) if spec_name is not None: # Generic ctor call: list[str](pool, 8) -> __new__ + __before_init__ + __init__. # Do not use spec_name as func_name (star-import fallback would pick a wrong SHA1). @@ -429,7 +429,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if sub_cast_arg is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, sub_cast_arg, sub_cast_ty, cl.args.get(0), trans) # Generic class template not found: the defining module may not be imported. - gt_err: str = pool.alloc(256) + gt_err: char* = pool.alloc(256) if gt_err is not None: viperlib.snprintf(gt_err, 256, "Generic class '%s': template not found; the defining module may not be imported", gen_class_name) self.Gen.TypeGenErr.fatal_error(gen_nm_node, gt_err) @@ -488,14 +488,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): mod_qual_done: int = 0 if trans is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_qc0: ast.Attribute* = ast.Attribute*(cl.func) - mod_path0: str = None + mod_path0: char* = None if at_qc0.value is not None and at_qc0.value.kind() == ast.ASTKind.Name: mod_nm0: ast.Name* = ast.Name*(at_qc0.value) if mod_nm0.id is not None: mod_path0 = mod_nm0.id elif at_qc0.value is not None and at_qc0.value.kind() == ast.ASTKind.Attribute: mod_path0 = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_qc0.value) if mod_path0 is not None: if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, mod_path0) != 0: - mod_sha1_0: str = self._lookup_module_sha1(mod_path0) + mod_sha1_0: char* = self._lookup_module_sha1(mod_path0) if mod_sha1_0 is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_0) mod_qual_done = 1 @@ -515,7 +515,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if imp_ok != 0: # Module-qualified construction: resolve by project module SHA1, not trans.ModuleSha1 # (the current file); otherwise the bare-name fallback picks the wrong same-name class. - mod_sha1_qc2: str = None + mod_sha1_qc2: char* = None if mod_nm_qc.id is not None: mod_sha1_qc2 = self._lookup_module_sha1(mod_nm_qc.id) if mod_sha1_qc2 is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc2) if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) @@ -523,11 +523,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): elif at_qc.value is not None and at_qc.value.kind() == ast.ASTKind.Attribute: # Multi-level module path construction: win32.fileio.File(...); build the path via # attr_module_path_str, check the full import, then find the struct by that module's SHA1. - mod_path_qc: str = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_qc.value) + mod_path_qc: char* = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_qc.value) if mod_path_qc is not None: imp_ok_qc: int = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path_qc) if imp_ok_qc != 0: - mod_sha1_qc: str = self._lookup_module_sha1(mod_path_qc) + mod_sha1_qc: char* = self._lookup_module_sha1(mod_path_qc) if mod_sha1_qc is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc) if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) if gen_ctor_entry is not None: struct_ty = gen_ctor_entry.Ty @@ -535,14 +535,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # original name, so resolve alias -> original before find_struct to avoid a link-time undefined reference. if gen_ctor_entry is None and trans is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name: if trans._from_imports is not None: - ctor_sha1: str = self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) + ctor_sha1: char* = self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) if ctor_sha1 is not None: - ctor_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, func_name) + ctor_orig: char* = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, func_name) if ctor_orig is not None: # Copy into a separate NUL-terminated buffer (the from_imports buffer is not terminated). co_len: sizet = 0 while ctor_orig[co_len] != ' ' and ctor_orig[co_len] != '\0': co_len += 1 - co_buf: str = pool.alloc(co_len + 1) + co_buf: char* = pool.alloc(co_len + 1) if co_buf is not None: for co_i in range(int(co_len)): co_buf[co_i] = ctor_orig[co_i] co_buf[co_len] = '\0' @@ -614,7 +614,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): ais_bare: sizet = sizet(aip_bare) # [D25 fail-fast] Never default to "int": with no hint and too few args it would # wrongly specialize to list[int]/Box[int] (4-byte elements, pointer truncation/crash). - ta_bare: str = None + ta_bare: char* = None if ais_bare < can: ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, cargs.get(ais_bare), func_name, trans) if ta_bare is None: # [C2] Keyword-only arg (Box(v=42)): match the keyword by __init__ param name @@ -629,7 +629,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if ta_bare is None: self.Gen.TypeGenErr.fatal_error(cl, f"Cannot infer type argument {tpi_bare + 1} of generic class '{func_name}' from the arguments, " f"silent default to int is forbidden (it produces wrong specializations such as list[int] -> elements treated as 4 bytes/i32 -> pointer truncation crash); " f"annotate the argument type or annotate explicitly, e.g. {func_name}[Type](...)", "TypeError") inferred_args_bare.append(ta_bare) - spec_name_bare: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, func_name, inferred_args_bare) + spec_name_bare: char* = self.Gen.ClassGenGeneric._specialize_generic_class(trans, func_name, inferred_args_bare) if spec_name_bare is not None: return self.Gen.CallGenCtor._translate_generic_ctor_call(pool, builder, mod, spec_name_bare, cl, trans, func_name) # REnum variant construction: ClassName.VariantName(args...), e.g. LLVMType.Int(1). Must run @@ -639,7 +639,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Name: rc_cls_node: ast.Name* = ast.Name*(rc_at.value) if rc_cls_node.id is not None: - rc_cls_name: str = rc_cls_node.id + rc_cls_name: char* = rc_cls_node.id # Check whether ClassName is a registered REnum; also use _is_renum_by_entry (a __tag # makes it an REnum) so a missing variant table does not silently fall through to a misleading error. if self.Gen.ClassGenEnum._is_renum_class_name(rc_cls_name) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rc_cls_name) != 0: @@ -652,21 +652,21 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): elif rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Attribute: # Module-qualified REnum variant: mod.Class.Variant(args...), e.g. mlirlite.LLVMType.Struct(...). # Only require the leftmost module imported and the class name in the global REnum table. - rc_mq_path: str = self.Gen.ExprGenAttr._attr_module_path_str(pool, rc_at.value) + rc_mq_path: char* = self.Gen.ExprGenAttr._attr_module_path_str(pool, rc_at.value) if rc_mq_path is not None: - rc_mq_dot: str = string.strrchr(rc_mq_path, 46) # 46 = ord('.') + rc_mq_dot: char* = string.strrchr(rc_mq_path, 46) # 46 = ord('.') if rc_mq_dot is not None and rc_mq_dot[1] != '\0': # Module path = everything before the last segment (multi-level supported); use # strlen integer differences, not pointer subtraction (which emits illegal IR). rc_mq_len: sizet = string.strlen(rc_mq_path) - string.strlen(rc_mq_dot + 1) - 1 - rc_mq_mod: str = pool.alloc(rc_mq_len + 1) + rc_mq_mod: char* = pool.alloc(rc_mq_len + 1) if rc_mq_mod is not None: string.memcpy(rc_mq_mod, rc_mq_path, rc_mq_len) rc_mq_mod[rc_mq_len] = '\0' rc_mq_imp: int = 1 if trans is not None and trans._imported_modules is not None: rc_mq_imp = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, rc_mq_mod) if rc_mq_imp != 0: - rc_mq_cls: str = rc_mq_dot + 1 + rc_mq_cls: char* = rc_mq_dot + 1 # Check whether the class name is a registered REnum class. if self.Gen.ClassGenEnum._is_renum_class_name(rc_mq_cls) != 0: rc_mq_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(rc_mq_cls, func_name) @@ -677,9 +677,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: if func_name is not None and trans is not None: if self.Gen.AsyncGen.is_async_func(trans, func_name) != 0: - can_buf: str = pool.alloc(64) + can_buf: char* = pool.alloc(64) if can_buf is not None: viperlib.snprintf(can_buf, 64, "create_%s", func_name) - create_an: str = self.Gen.FuncGenBase._mangle_func_name(trans, can_buf, 0) + create_an: char* = self.Gen.FuncGenBase._mangle_func_name(trans, can_buf, 0) create_fn_an: mlirlite.Function* = self.find_func_in_module(mod, create_an) if create_fn_an is not None: frame_ty_an: mlirlite.LLVMType* = self.Gen.AsyncGen._lookup_coro_frame(trans, func_name) @@ -719,7 +719,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: # Bare-name call: allow exact + suffix matching. Custom decorator wrapper rewrite: original # name -> __decor_wrap_{name} (wrapper is generated at function-translation end and is reachable). - decor_wrap_nm: str = self.Gen.ClassGenBase.lookup_decor_wrapper(func_name) + decor_wrap_nm: char* = self.Gen.ClassGenBase.lookup_decor_wrapper(func_name) if decor_wrap_nm is not None: found_func = self.find_func_in_module(mod, decor_wrap_nm) else: # Bare-name call to a function defined in this module: hit the module function table first (authoritative for module-level names), then fall back to the module list scan. @@ -727,7 +727,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if actual_funcs is not None: # Prefer same-module functions: the _funcs table is polluted by dependency stubs, # so pass trans.ModuleSha1 to match the "{ModuleSha1}.{name}" entry first (AstTest root cause). - tbl_owner_sha1: str = None + tbl_owner_sha1: char* = None if trans is not None: tbl_owner_sha1 = trans.ModuleSha1 mod_fn_tb = self.Gen.CallGenLeafKit.find_func_in_table(actual_funcs, actual_func_count, func_name, tbl_owner_sha1) if mod_fn_tb is not None: @@ -735,7 +735,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 重载:本模块同名 >=2 时按实参静态类型决议(返回值不参与)。 # 单候选维持原行为零开销;候选 >=2 且有实参无法定型 -> resolve 内 fail-fast。 if actual_funcs is not None: - ovl_owner: str = None + ovl_owner: char* = None if trans is not None: ovl_owner = trans.ModuleSha1 ovl_cnt: int = self.Gen.CallGenLeafKit.count_owned_overloads(actual_funcs, actual_func_count, func_name, ovl_owner) if ovl_cnt >= 2: @@ -745,13 +745,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: # No table entry: fall back to scanning FuncHead, also passing owner_sha1 so an # inactive same-name forward declaration does not get mis-bound to an earlier stub. - ff_owner_sha1: str = None + ff_owner_sha1: char* = None if trans is not None: ff_owner_sha1 = trans.ModuleSha1 found_func = self.find_func_in_module(mod, func_name, ff_owner_sha1) # Reject suffix matches that hit a class method (SHA1.Class.method): a bare-name call sharing a # name with a module function would bind to the method and recurse infinitely (stack overflow). if found_func is not None: - bn_name: str = mlirlite.function_get_name(found_func) + bn_name: char* = mlirlite.function_get_name(found_func) if bn_name is not None: bn_dots: int = 0 bni2: sizet = 0 @@ -760,7 +760,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): bni2 += 1 if bn_dots >= 2: # Extract segment 2 (SHA1.Class.method -> Class; SHA1.submod.func -> submod). - bn_seg2: str = pool.alloc(64) + bn_seg2: char* = pool.alloc(64) if bn_seg2 is not None: bn_seg2[0] = '\0' bsi2: sizet = 0 @@ -782,10 +782,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: # 跨模块重载:先从接收者路径解析目标模块 SHA1,再在候选集里决议。 # vpi 注入的重载符号是 {sha1}.name_v{hash}、函数表项名带后缀,所以用 prefix 模式。 - xm_sha1_ovl: str = None + xm_sha1_ovl: char* = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute and trans is not None and trans._imported_modules is not None: xm_at_ovl: ast.Attribute* = ast.Attribute*(cl.func) - xm_path_ovl: str = None + xm_path_ovl: char* = None if xm_at_ovl is not None and xm_at_ovl.value is not None: if xm_at_ovl.value.kind() == ast.ASTKind.Name: xm_nm_ovl: ast.Name* = ast.Name*(xm_at_ovl.value) @@ -815,20 +815,20 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if xm_at is not None and xm_at.value is not None and trans is not None and trans._imported_modules is not None: # Module path: one-level Name (syslibtest_impl.run) or nested Attribute (os._win32.exists). # The nested case must be validated too, else it suffix-matches this module's own define (recursion). - xm_mod_path: str = None + xm_mod_path: char* = None if xm_at.value.kind() == ast.ASTKind.Name: xm_nm: ast.Name* = ast.Name*(xm_at.value) if xm_nm.id is not None: xm_mod_path = xm_nm.id elif xm_at.value.kind() == ast.ASTKind.Attribute: xm_mod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xm_at.value) if xm_mod_path is not None: if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, xm_mod_path) != 0: - mod_sha1_chk: str = self._lookup_module_sha1(xm_mod_path) + mod_sha1_chk: char* = self._lookup_module_sha1(xm_mod_path) if mod_sha1_chk is None and trans._from_imports is not None: # import X as Y (e.g. import fat32_diskio as diskio): resolve the alias before # lookup, else this check is skipped and the suffix match hits a same-name local function. mod_sha1_chk = self.Gen.StructGen._resolve_module_sha1(xm_mod_path, trans._from_imports) if mod_sha1_chk is not None: - ff_nm2: str = mlirlite.function_get_name(found_func) + ff_nm2: char* = mlirlite.function_get_name(found_func) if ff_nm2 is not None: if string.strncmp(ff_nm2, mod_sha1_chk, 16) != 0: # ExportT / t.State 型跨模块函数**定义与声明都用裸名**(stdlib.free、 @@ -848,7 +848,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if cx_ok == 0: if self.Gen.CallGenBase._is_reexport_owner(pool, mod_sha1_chk, func_name, ff_nm2) != 0: cx_ok = 1 if cx_ok == 0: found_func = None - ff_name: str = mlirlite.function_get_name(found_func) + ff_name: char* = mlirlite.function_get_name(found_func) if ff_name is not None: ff_dots: int = 0 ffi2: sizet = 0 @@ -857,7 +857,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): ffi2 += 1 if ff_dots >= 2: # Extract segment 2 (SHA1.Class.method -> Class; SHA1.submod.func -> submod). - seg2: str = pool.alloc(64) + seg2: char* = pool.alloc(64) if seg2 is not None: seg2[0] = '\0' si: sizet = 0 @@ -891,9 +891,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if found_func is None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name and string.strcmp(func_name, "abs") == 0 and can == 1: abs_arg: ast.AST* = cargs.get(0) if abs_arg is not None: - abs_cls: str = self.Gen.CallGenProp._resolve_obj_class_name(pool, trans, abs_arg) + abs_cls: char* = self.Gen.CallGenProp._resolve_obj_class_name(pool, trans, abs_arg) if abs_cls is not None: - abs_sc: str = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, abs_cls, "__abs__", trans) + abs_sc: char* = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, abs_cls, "__abs__", trans) if abs_sc is not None: abs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, abs_arg, None, 0, trans) if abs_val is not None: return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, abs_sc, "__abs__", abs_val, None, 0, trans) @@ -903,7 +903,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # builtins auto-link: when no C library matches, link ord/chr etc. from the builtins module by # creating a {builtins_sha1}.{name} declare with the agreed signature (ord(i8)->i32, chr(i32)->i8). if found_func is None: - bi_sha1: str = self._lookup_module_sha1("builtins") + bi_sha1: char* = self._lookup_module_sha1("builtins") if bi_sha1 is not None: bi_ret: mlirlite.LLVMType* = None bi_p1: mlirlite.LLVMType* = None @@ -925,10 +925,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): bi_ret = mlirlite.Int32(pool) bi_p1 = mlirlite.Int32(pool) if bi_ret is not None: - bi_sym: str = func_name + bi_sym: char* = func_name if self.Gen.CallGenBase.is_cexport_func(bi_sha1, func_name) == 0: bi_sym_len: sizet = string.strlen(bi_sha1) + string.strlen(func_name) + 2 - bi_sym_buf: str = pool.alloc(bi_sym_len) + bi_sym_buf: char* = pool.alloc(bi_sym_len) if bi_sym_buf is not None: viperlib.snprintf(bi_sym_buf, bi_sym_len, "%s.%s", bi_sha1, func_name) bi_sym = bi_sym_buf @@ -950,9 +950,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): vpi_ret_ty: mlirlite.LLVMType* = None # Source module SHA1 for cross-module return-type resolution (assigned only in the Attribute # branch). Must be initialized to None, else a bare call reads stack garbage and crashes. - mod_ret_sha1: str = None + mod_ret_sha1: char* = None # Module path (assigned only for Attribute); declared outside the if so the bare-name fallback can read it safely. - mod_path_ret: str = None + mod_path_ret: char* = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_ret: ast.Attribute* = ast.Attribute*(cl.func) # Resolve the callee module path: both one-level (stdlib.free) and multi-level @@ -964,17 +964,17 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if mod_path_ret is not None: # import X as Y (e.g. import lib.core.Gen.GenApi as GenApi): an exact module-name lookup # cannot resolve the alias and would wrongly fail-fast; use _resolve_module_sha1 (alias restore + exact/suffix). - fi_from_rt: str = None + fi_from_rt: char* = None if trans is not None: fi_from_rt = trans._from_imports mod_ret_sha1 = self.Gen.StructGen._resolve_module_sha1(mod_path_ret, fi_from_rt) if mod_ret_sha1 is not None: # Lazy in-function import: VpiReader imports HandlesExprCall, so a top-level import would cycle. VpiReader._ensure_vpi_ret_annot_loaded(mod_ret_sha1, self.Gen.CallGenBase.TempDir) - ret_annot_fc: str = VpiReader._lookup_vpi_ret_annot(mod_ret_sha1, None, func_name) + ret_annot_fc: char* = VpiReader._lookup_vpi_ret_annot(mod_ret_sha1, None, func_name) if ret_annot_fc is None: # Package vpi miss (the function is defined in a submodule, e.g. fltk.Fl_Input_value in # fltk._cfl_input): use re-export to locate the defining module, then query its vpi. - rr_src: str = self.Gen.ImportsGen.lookup_reexport_call(mod_ret_sha1, func_name) + rr_src: char* = self.Gen.ImportsGen.lookup_reexport_call(mod_ret_sha1, func_name) if rr_src is None: rr_src = self._lookup_reexport_from_vpi(pool, mod_ret_sha1, func_name) if rr_src is not None: rr_total: sizet = string.strlen(rr_src) @@ -985,11 +985,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): rr_start: sizet = rr_i while rr_i < rr_total and rr_src[rr_i] != ' ': rr_i += 1 rr_len: sizet = rr_i - rr_start - rr_buf: str = pool.alloc(rr_len + 1) + rr_buf: char* = pool.alloc(rr_len + 1) if rr_buf is not None: string.strncpy(rr_buf, rr_src + rr_start, rr_len) rr_buf[rr_len] = '\0' - rr_sha1: str = self._lookup_module_sha1(rr_buf) + rr_sha1: char* = self._lookup_module_sha1(rr_buf) # Re-export sources may be registered under a qualified # module name; fall back to suffix lookup on exact miss. if rr_sha1 is None: rr_sha1 = self._lookup_module_sha1_suffix(rr_buf) @@ -1013,21 +1013,21 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 结果被丢弃(独立调用语句)时不 fail-fast:占位 i32 无害,没必要中断编译。 if trans is not None and trans._declare_only == 0 and trans._discard_result == 0: vpi_rc_d: int = 0 - vpi_annot_d: str = None + vpi_annot_d: char* = None if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: vpi_rc_d = VpiReader._ensure_vpi_ret_annot_loaded(mod_ret_sha1, self.Gen.CallGenBase.TempDir) vpi_annot_d = VpiReader._lookup_vpi_ret_annot(mod_ret_sha1, None, func_name) - annot_s_d: str = "-" + annot_s_d: char* = "-" if vpi_annot_d is not None: annot_s_d = vpi_annot_d # sha1 来源拆解:exact / suffix 各自返回什么,用来区分"存表里就是错的" # 与"后缀匹配撞到了别的模块"(两者修法完全不同)。 - ex_s_d: str = "-" + ex_s_d: char* = "-" if mod_path_ret is not None: - _ex_d: str = self.Gen.CallGenBase._lookup_module_sha1(mod_path_ret) + _ex_d: char* = self.Gen.CallGenBase._lookup_module_sha1(mod_path_ret) if _ex_d is not None: ex_s_d = _ex_d - sf_s_d: str = "-" + sf_s_d: char* = "-" if mod_path_ret is not None: - _sf_d: str = self.Gen.CallGenBase._lookup_module_sha1_suffix(mod_path_ret) + _sf_d: char* = self.Gen.CallGenBase._lookup_module_sha1_suffix(mod_path_ret) if _sf_d is not None: sf_s_d = _sf_d # 走 VPC Diag(源码行 + 调用栈),而不是单行 VLogger.error: # 单行输出丢掉了位置与调用链,无法定位到底是谁在什么上下文里调用了它。 @@ -1073,9 +1073,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): c_struct: mlirlite.LLVMType* = None if c_obj is not None: c_struct = self.Gen.StructGen.get_struct_type_from_value(c_obj) if c_struct is not None: - c_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, c_struct) + c_cls: char* = self.Gen.StructGen.get_class_name_by_type(pool, c_struct) if c_cls is not None: - c_call_cls: str = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, c_cls, "__call__", trans) + c_call_cls: char* = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, c_cls, "__call__", trans) if c_call_cls is not None: return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, c_call_cls, "__call__", c_obj, cl, trans) # Closure variable (nested function hoisted and registered): extract fn_ptr/env_ptr and call indirectly. if self.Gen.CallGenLeafKit.is_closure_name(func_name) != 0: @@ -1086,7 +1086,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # holds {fn_ptr, env_ptr} and must pass env, else a direct call jumps into closure data and crashes. ve_fp: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, func_name) is_cptr_annot_fp: int = 0 - fp_annot: str = self.Gen.VarGen.var_annot_class_name(ve_fp) + fp_annot: char* = self.Gen.VarGen.var_annot_class_name(ve_fp) if fp_annot is not None: # [S4] PtrT marker = annotation base name exactly "PtrT": t.Callable[[A],R] also resolves to # Ptr(i8) (same Spec), so only the annotation name can carry the marker; substring matching would misfire. @@ -1152,7 +1152,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): fpi += 1 if fp is not None: fpty = mlirlite.param_get_ty(fp) # Value-reference params (&T / &temp T): auto-address the argument (same-module callee). - ao_name: str = None + ao_name: char* = None if found_func is not None: ao_name = mlirlite.function_get_name(found_func) arg_val: mlirlite.Value* = self.Gen.CallGenBase.translate_call_arg(builder, pool, mod, trans, ao_name, int(ai), arg, fpty, "param") if arg_val is not None: @@ -1178,15 +1178,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): ext_param_ty: mlirlite.LLVMType* = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_pt: ast.Attribute* = ast.Attribute*(cl.func) - mpath_pt: str = None + mpath_pt: char* = None if at_pt.value is not None and at_pt.value.kind() == ast.ASTKind.Name: nm_pt: ast.Name* = ast.Name*(at_pt.value) mpath_pt = nm_pt.id elif at_pt.value is not None and at_pt.value.kind() == ast.ASTKind.Attribute: mpath_pt = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_pt.value) if mpath_pt is not None: - fi_pt: str = None + fi_pt: char* = None if trans is not None: fi_pt = trans._from_imports - sha_pt: str = self.Gen.StructGen._resolve_module_sha1(mpath_pt, fi_pt) + sha_pt: char* = self.Gen.StructGen._resolve_module_sha1(mpath_pt, fi_pt) if sha_pt is not None: if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_param_annot_loaded(sha_pt, self.Gen.CallGenBase.TempDir) ext_param_ty = VpiReader._resolve_vpi_param_annot_seg(pool, sha_pt, None, func_name, ai, mlirlite.Int32(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool))) @@ -1266,10 +1266,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): df_param_count: int = 0 # Compute the callee module SHA1 as a qualifier key (module.func -> that module; bare -> current), # so usb.uhci.init(1 arg) does not wrongly match mm.init (5 params) and add extra arguments. - dfx_callee_sha: str = None + dfx_callee_sha: char* = None if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: dfx_at: ast.Attribute* = ast.Attribute*(cl.func) - dfx_mod_path: str = None + dfx_mod_path: char* = None if dfx_at.value is not None and dfx_at.value.kind() == ast.ASTKind.Name: dfx_mn: ast.Name* = ast.Name*(dfx_at.value) if dfx_mn.id is not None: dfx_mod_path = dfx_mn.id @@ -1281,7 +1281,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # and returns None for `import X.Y as Z` (Z is not a module name). Without the alias restore the # qualifier degrades to the current module SHA1, so find_func_defaults misses the defining module # and the defaults are never filled (rhttps.get(url, verify) emits 2 operands for a 3-param callee). - dfx_fi: str = None + dfx_fi: char* = None if trans is not None: dfx_fi = trans._from_imports dfx_callee_sha = self.Gen.StructGen._resolve_module_sha1(dfx_mod_path, dfx_fi) if dfx_callee_sha is None and self.Gen.TypeGenBase is not None: dfx_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 @@ -1299,10 +1299,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Package re-export fallback (e.g. json.write defined in includes/json/__writer.vp): the defaults # table is keyed by the defining module SHA1, so re-resolve the re-export and query again (else defaults are skipped). if gd_entry is None and dfx_callee_sha is not None: - rr_src_dx: str = self.Gen.ImportsGen.lookup_reexport_call(dfx_callee_sha, func_name) + rr_src_dx: char* = self.Gen.ImportsGen.lookup_reexport_call(dfx_callee_sha, func_name) if rr_src_dx is None: rr_src_dx = self._lookup_reexport_from_vpi(pool, dfx_callee_sha, func_name) if rr_src_dx is not None: - rr_sha_dx: str = self._lookup_module_sha1(rr_src_dx) + rr_sha_dx: char* = self._lookup_module_sha1(rr_src_dx) if rr_sha_dx is not None: gd_entry = self.Gen.CallGenLeafKit.find_func_defaults(func_name, rr_sha_dx) # 键失配兜底:链式接收者(`self.Gen.ExprGenMixin.translate_value(...)`)解析不出发起模块, # dfx_callee_sha 退化成调用方自己的 SHA1,限定查表落空 —— 由后面的 _fill_defaults_late @@ -1319,7 +1319,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): dfx_cnt: int = 0 dfx_p: mlirlite.Param* = mlirlite.function_get_param_head(found_func) while dfx_p is not None: - dfx_nm: str = mlirlite.param_get_name(dfx_p) + dfx_nm: char* = mlirlite.param_get_name(dfx_p) if dfx_nm is None or (string.strcmp(dfx_nm, "%__eh_msg_out__") != 0 and string.strcmp(dfx_nm, "%__eh_code_out__") != 0): dfx_cnt += 1 dfx_p = mlirlite.param_get_next(dfx_p) @@ -1359,7 +1359,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): fc_cnt: int = 0 fc_p: mlirlite.Param* = mlirlite.function_get_param_head(found_func) while fc_p is not None: - fp_nm_z: str = mlirlite.param_get_name(fc_p) + fp_nm_z: char* = mlirlite.param_get_name(fc_p) if fp_nm_z is None or (string.strcmp(fp_nm_z, "%__eh_msg_out__") != 0 and string.strcmp(fp_nm_z, "%__eh_code_out__") != 0): fc_cnt += 1 fc_p = mlirlite.param_get_next(fc_p) @@ -1384,12 +1384,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Use the actual function name from the module (may carry a SHA1 prefix); ExternT/State/ExportT # functions use the bare name. Both declare and define must use found_func.Name (mismatched names cause undefined references). - call_name: str = func_name + call_name: char* = func_name # Original function name (recorded for aliased imports, e.g. from X import parse as json_parse -> "parse"), # used to re-infer the return type after alias handling so _infer_external_func_ret_ty can match. - orig_func_name: str = None + orig_func_name: char* = None if found_func is not None: - found_name: str = mlirlite.function_get_name(found_func) + found_name: char* = mlirlite.function_get_name(found_func) if found_name is not None: call_name = found_name # ExportT bare-name fallback: a cross-module stub declare may carry a SHA1 prefix while the @@ -1397,7 +1397,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if found_func.IsDeclared != 0: # Use the single source of truth GenApi.sha1_prefix_len (converged in C10). if GenApi.sha1_prefix_len(found_name) != 0: - cx_sha1_buf: str = pool.alloc(17) + cx_sha1_buf: char* = pool.alloc(17) if cx_sha1_buf is not None: string.memcpy(cx_sha1_buf, found_name, 16) cx_sha1_buf[16] = '\0' @@ -1409,13 +1409,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if xmod_at.value is not None and (xmod_at.value.kind() == ast.ASTKind.Name or xmod_at.value.kind() == ast.ASTKind.Attribute): # Module path: one-level Name (string.strchr) or nested Attribute (os._win32.exists). The nested # case must be resolved too, else it suffix-matches this module's own define (infinite recursion). - xmod_path: str = None + xmod_path: char* = None if xmod_at.value.kind() == ast.ASTKind.Name: xmod_nm: ast.Name* = ast.Name*(xmod_at.value) if xmod_nm.id is not None: xmod_path = xmod_nm.id else: xmod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xmod_at.value) if xmod_path is not None: - mod_sha1: str = self._lookup_module_sha1(xmod_path) + mod_sha1: char* = self._lookup_module_sha1(xmod_path) if mod_sha1 is not None: # fast-fail: a module-qualified call requires the module to be imported by this file; # the global SHA1 store contains all scanned includes, so an unimported module would silently resolve. @@ -1423,13 +1423,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if trans is not None and trans._imported_modules is not None: is_xmod_imported = self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, xmod_path) if is_xmod_imported == 0: - err_ni: str = pool.alloc(256) + err_ni: char* = pool.alloc(256) if err_ni is not None: viperlib.snprintf(err_ni, 256, "Cross-module call '%s.%s': module '%s' not imported (import %s first)", xmod_path, func_name, xmod_path, xmod_path) self.Gen.TypeGenErr.fatal_error(xmod_at, err_ni) self.Gen.TypeGenErr.fatal_error(xmod_at, "Cross-module call: module not imported") # Check whether it is a re-export function (e.g. ast._lexer_init actually defined in ast.lexer). - reexport_src: str = self.Gen.ImportsGen.lookup_reexport_call(mod_sha1, func_name) + reexport_src: char* = self.Gen.ImportsGen.lookup_reexport_call(mod_sha1, func_name) if reexport_src is None: # Re-export table miss (includes modules with existing stub/text are not fully translated, # so the table may be empty): resolve the module's .vpi from-import to locate the defining module. @@ -1446,11 +1446,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): cs_start: sizet = cs_i while cs_i < cs_total and reexport_src[cs_i] != ' ': cs_i += 1 cs_seg: sizet = cs_i - cs_start - cs_buf: str = pool.alloc(cs_seg + 1) + cs_buf: char* = pool.alloc(cs_seg + 1) if cs_buf is not None: string.strncpy(cs_buf, reexport_src + cs_start, cs_seg) cs_buf[cs_seg] = '\0' - cand_sha1: str = self._lookup_module_sha1(cs_buf) + cand_sha1: char* = self._lookup_module_sha1(cs_buf) if cand_sha1 is None: cand_sha1 = self._lookup_module_sha1_suffix(cs_buf) if cand_sha1 is not None: if self.Gen.CallGenBase.is_cexport_func(cand_sha1, func_name) != 0 or self._is_state_func_from_vpi(pool, cand_sha1, func_name) != 0: @@ -1473,7 +1473,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if VpiReader._lookup_vpi_ret_annot(mod_sha1, None, func_name) is not None: orig_has_def = 1 if orig_has_def == 0: # Original module does not define it: fall back to the first candidate (e.g. ast._lexer_init in ast.lexer). - reexport_sha1: str = self._lookup_module_sha1(reexport_src) + reexport_sha1: char* = self._lookup_module_sha1(reexport_src) if reexport_sha1 is None: reexport_sha1 = self._lookup_module_sha1_suffix(reexport_src) if reexport_sha1 is not None: mod_sha1 = reexport_sha1 # ExportT functions define with the bare name (@strlen), so the cross-module call must use the bare name too. @@ -1486,7 +1486,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): call_name = func_name else: mangled_len: sizet = string.strlen(mod_sha1) + string.strlen(func_name) + 2 - mangled: str = pool.alloc(mangled_len) + mangled: char* = pool.alloc(mangled_len) if mangled is not None: viperlib.snprintf(mangled, mangled_len, "%s.%s", mod_sha1, func_name) call_name = mangled @@ -1501,7 +1501,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if is_imported_mod != 0: # Aliased import (import X as Y): Y is in _imported_modules but the exact SHA1 lookup fails # (mod_arr holds file names); try from_imports (alias -> full name -> suffix SHA1) with allow_star_fallback=0. - alias_sha1: str = None + alias_sha1: char* = None if trans is not None and trans._from_imports is not None: alias_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) if alias_sha1 is not None: if self.Gen.CallGenBase.is_cexport_func(alias_sha1, func_name) != 0: call_name = func_name @@ -1510,13 +1510,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): call_name = func_name else: AliasMangledLen: sizet = string.strlen(alias_sha1) + string.strlen(func_name) + 2 - alias_mangled: str = pool.alloc(AliasMangledLen) + alias_mangled: char* = pool.alloc(AliasMangledLen) if alias_mangled is not None: viperlib.snprintf(alias_mangled, AliasMangledLen, "%s.%s", alias_sha1, func_name) call_name = alias_mangled else: # Imported module but SHA1 unregistered: the module was not compiled, so error out immediately. - err_msg_imp: str = pool.alloc(256) + err_msg_imp: char* = pool.alloc(256) if err_msg_imp is not None: viperlib.snprintf(err_msg_imp, 256, "Module '%s' is imported but its SHA1 is not registered (the module was not compiled)", xmod_path) self.Gen.TypeGenErr.fatal_error(xmod_at, err_msg_imp) @@ -1524,14 +1524,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: # Check whether it is a from-import name (e.g. from .__types import LLVMType): LLVMType is a # class, not a module, but Ptr is a module-level function of __types; disable star-import fallback. - from_sha1: str = None + from_sha1: char* = None if trans is not None and trans._from_imports is not None: from_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) if from_sha1 is not None: # ExportT functions define with the bare name, so the cross-module call must use the bare name. if self.Gen.CallGenBase.is_cexport_func(from_sha1, func_name) != 0: call_name = func_name else: fmangled_len: sizet = string.strlen(from_sha1) + string.strlen(func_name) + 2 - fmangled: str = pool.alloc(fmangled_len) + fmangled: char* = pool.alloc(fmangled_len) if fmangled is not None: viperlib.snprintf(fmangled, fmangled_len, "%s.%s", from_sha1, func_name) call_name = fmangled @@ -1547,12 +1547,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if base_defined == 0 and GenApi.is_nonlocal_name(trans, xmod_path) != 0: base_defined = 1 if base_defined == 0 and self.Gen.StructGen.find_struct(xmod_path) is not None: base_defined = 1 if base_defined == 0: - err_msg_ne: str = pool.alloc(256) + err_msg_ne: char* = pool.alloc(256) if err_msg_ne is not None: viperlib.snprintf(err_msg_ne, 256, "name '%s' is not defined (used as a module in '%s.%s'; missing an import?)", xmod_path, xmod_path, func_name) self.Gen.TypeGenErr.fatal_error(xmod_at, err_msg_ne, "NameError") self.Gen.TypeGenErr.fatal_error(xmod_at, f"name '{xmod_path}' is not defined", "NameError") - err_msg2: str = pool.alloc(256) + err_msg2: char* = pool.alloc(256) if err_msg2 is not None: viperlib.snprintf(err_msg2, 256, "Cross-module call '%s.%s': module SHA1 not found", xmod_path, func_name) self.Gen.TypeGenErr.fatal_error(xmod_at, err_msg2) @@ -1561,18 +1561,18 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Bare-name call (not Attribute): check from_imports. Star-import fallback is disabled for calls # (star import is for types/constants); a missed function then fails fast at compile time instead of linking wrong. if trans is not None and trans._from_imports is not None: - bare_sha1: str = self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) + bare_sha1: char* = self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) if bare_sha1 is not None: # Alias handling: from X import Y as Z -> calling Z must mangle with Y (e.g. from json.__parser # import parse as json_parse -> SHA1.parse, not SHA1.json_parse). - bare_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, func_name) - bare_func_name: str = func_name + bare_orig: char* = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, func_name) + bare_func_name: char* = func_name if bare_orig is not None: # bare_orig points into the from_imports buffer and is not NUL-terminated, so copy it # into a separate buffer (truncating at space or NUL). bo_len: sizet = 0 while bare_orig[bo_len] != ' ' and bare_orig[bo_len] != '\0': bo_len += 1 - bo_buf: str = pool.alloc(bo_len + 1) + bo_buf: char* = pool.alloc(bo_len + 1) if bo_buf is not None: for bo_i in range(int(bo_len)): bo_buf[bo_i] = bare_orig[bo_i] bo_buf[bo_len] = '\0' @@ -1582,28 +1582,28 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): orig_func_name = bare_func_name # Re-export resolution: a from-imported bare function may actually be defined in a submodule # (e.g. dump defined in ast.base, ast/__init__ only re-exports), so redirect to the defining module SHA1. - reexport_src2: str = self.Gen.ImportsGen.lookup_reexport_call(bare_sha1, bare_func_name) + reexport_src2: char* = self.Gen.ImportsGen.lookup_reexport_call(bare_sha1, bare_func_name) if reexport_src2 is None: # Re-export table miss: resolve the module's .vpi from-import on demand. reexport_src2 = self._lookup_reexport_from_vpi(pool, bare_sha1, bare_func_name) if reexport_src2 is not None: - reexport_sha1_2: str = self._lookup_module_sha1(reexport_src2) + reexport_sha1_2: char* = self._lookup_module_sha1(reexport_src2) if reexport_sha1_2 is not None: bare_sha1 = reexport_sha1_2 if self.Gen.CallGenBase.is_cexport_func(bare_sha1, bare_func_name) != 0: call_name = bare_func_name else: bare_mangled_len: sizet = string.strlen(bare_sha1) + string.strlen(bare_func_name) + 2 - bare_mangled: str = pool.alloc(bare_mangled_len) + bare_mangled: char* = pool.alloc(bare_mangled_len) if bare_mangled is not None: viperlib.snprintf(bare_mangled, bare_mangled_len, "%s.%s", bare_sha1, bare_func_name) call_name = bare_mangled else: - err_msg3: str = pool.alloc(256) + err_msg3: char* = pool.alloc(256) if err_msg3 is not None: viperlib.snprintf(err_msg3, 256, "Bare-name call '%s' is undefined and not imported", func_name) self.Gen.TypeGenErr.fatal_error(node, err_msg3) self.Gen.TypeGenErr.fatal_error(node, "Bare-name call undefined and not imported") else: - err_msg4: str = pool.alloc(256) + err_msg4: char* = pool.alloc(256) if err_msg4 is not None: viperlib.snprintf(err_msg4, 256, "Bare-name call '%s' is undefined and not imported", func_name) self.Gen.TypeGenErr.fatal_error(node, err_msg4) @@ -1622,12 +1622,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # returning functions and the default i32 truncates them; the authority is text.ll define, then the vpi annotation. if self.Gen.CallGenLib._is_sha1_mangled_call(call_name) != 0: if trans is None or trans._declare_only == 0: - cf_dot: str = string.strchr(call_name, '.') - cf_last: str = string.strrchr(call_name, '.') + cf_dot: char* = string.strchr(call_name, '.') + cf_last: char* = string.strrchr(call_name, '.') if cf_dot is not None and cf_last is not None: - cf_sha1: str = stdlib.malloc(17) + cf_sha1: char* = stdlib.malloc(17) cf_bare_len: sizet = string.strlen(call_name) - (sizet(uint64(cf_last) - uint64(call_name))) - 1 - cf_bare: str = stdlib.malloc(cf_bare_len + 1) + cf_bare: char* = stdlib.malloc(cf_bare_len + 1) if cf_sha1 is not None and cf_bare is not None: string.strncpy(cf_sha1, call_name, 16) cf_sha1[16] = '\0' @@ -1645,8 +1645,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # text.ll both key methods by class, so the class segment must be passed # through. Only when it names a registered class: `{sha}.submod.func` has # the same shape but its symbol is the bare module function. - cf_cls: str = None - cf_mid: str = cf_dot + 1 + cf_cls: char* = None + cf_mid: char* = cf_dot + 1 if uint64(cf_last) > uint64(cf_mid): cf_mid_len: sizet = sizet(uint64(cf_last) - uint64(cf_mid)) cf_cls_buf: bytes = stdlib.malloc(cf_mid_len + 1) @@ -1686,11 +1686,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 而 _ensure_method_declare 又会按 can 建短 declare —— 旧逻辑会把这个错误一路藏到 # mlir-opt 的 "incorrect number of operands"。含关键字实参或可变参数时跳过。 if self.Gen.CallGenLib._is_sha1_mangled_call(call_name) != 0 and (cl.keywords is None or len(cl.keywords) == 0): - ar_sha: str = pool.alloc(17) + ar_sha: char* = pool.alloc(17) if ar_sha is not None: string.strncpy(ar_sha, call_name, 16) ar_sha[16] = '\0' - ar_name: str = call_name + 17 + ar_name: char* = call_name + 17 ar_n: int = VpiReader.LookupParamCountByName(pool, ar_sha, ar_name) if ar_n >= 0 and int(can) != ar_n: # ar_n comes from a scan of the .vpi *text*. What this call actually binds to