diff --git a/App/lib/core/Gen/ExprGenCdef.vp b/App/lib/core/Gen/ExprGenCdef.vp index 8d361b5..7b82cd8 100644 --- a/App/lib/core/Gen/ExprGenCdef.vp +++ b/App/lib/core/Gen/ExprGenCdef.vp @@ -78,15 +78,26 @@ class ExprGenCdef(ExprGenBase.ExprGenBase): rel_path: str = rel_arr_ptr + ridx if rel_path[0] == '\0': return None - # 选择基础目录:rel_path 以 "lib/" 开头 → App 源文件(SourceDir); - # 以 "includes/" 开头 → includes 文件(去掉 "includes/" 前缀)。 - # 其他 rel_path(如 VKernel 的 "drivers/core/cpu/cpu.vp")无前缀, - # 无法从 rel_path 判断归属:先试 SourceDir(App 文件),文件不存在 - # 再试 IncludesDir(includes 文件的 RelPath 同样无前缀存储)。 - # 避免路径构建错误导致跨模块 CDefine 查找静默失败。 + # 选择基础目录(优先级): + # 1. 条目存储的 includes 根目录 IncDir(绝对路径,多 includes 目录 + # 支持):PopulateSha1MapStore 按每条目保存所属根目录,跨模块 + # CDefine 查找回退读源时按 IncDir 直接拼路径,避免"首 includes + # 目录"启发式对非首目录文件失效(Gargantua 多 includes 目录: + # stdint.vp 属于 TransPyC/includes,而 IncludesDir=首目录 ViperOS + # → 拼错路径 → 文件不存在 → XMOD-CD 误报根因)。 + # 2. rel_path 前缀启发式:以 "lib/" 开头 → App 源文件(SourceDir); + # "includes/" 开头 → includes 文件(去掉前缀);其他无前缀路径 + # (如 VKernel 的 "drivers/core/cpu/cpu.vp")先试 SourceDir, + # 文件不存在再试 IncludesDir。 base_dir: str = None rel_used: str = rel_path - if string.strlen(rel_path) >= 4: + inc_arr_ptr: bytes = StubMergerStore.GetSha1StoreIncdirArrPtr() + if inc_arr_ptr is not None: + iidx: t.CSizeT = t.CSizeT(idx_s) * StubMerger.MAX_INC_DIR_LEN + inc_dir: str = inc_arr_ptr + iidx + if inc_dir[0] != '\0': + base_dir = inc_dir + if base_dir is None and string.strlen(rel_path) >= 4: if (rel_path[0] == 'l' and rel_path[1] == 'i' and rel_path[2] == 'b' and rel_path[3] == '/'): base_dir = Config.SourceDir if Config.SourceDir is not None else Config.IncludesDir diff --git a/App/lib/core/Gen/ExprGenName.vp b/App/lib/core/Gen/ExprGenName.vp index b5f62e4..643d513 100644 --- a/App/lib/core/Gen/ExprGenName.vp +++ b/App/lib/core/Gen/ExprGenName.vp @@ -101,20 +101,28 @@ class ExprGenName(ExprGenBase.ExprGenBase): # 避免对普通变量名(mb/name/ptr/pool/self 等)误触发,造成严重性能损耗 if self.Gen.ExprGenCdef._is_cdefine_name_pattern(nm_id) != 0: if trans is not None: - cdef_val: t.CInt64T = self.Gen.ExprGenCdef._lookup_cross_module_cdefine( - pool, nm_id, trans._from_imports, trans._imported_modules, 0, node) - if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - if self.Gen.TypeGenCDef.is_cdefine_str() != 0: - cdef_sv2: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id) - if cdef_sv2 is not None: - return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_sv2, trans) - self.Gen.TypeGenErr.fatal_error(node, f"CDefine 字符串值缺失: {nm_id}", "InternalCompilerError") - # 跨模块浮点 CDefine 已缓存为 double(is_cdefine_double), - # 需返回浮点常量而非截断的整数 - dchk_nm: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id) - if self.Gen.TypeGenCDef.is_cdefine_double() != 0: - return llvmlite.ConstFloat(pool, llvmlite.Double(pool), dchk_nm) - return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val) + # ALL_CAPS 也可能是普通变量(如 Gargantua 的 + # CAM/FWD/RIGHT/UP: V3|t.CPtr 模块级全局)。若当前作用域 + # (含模块级 Root,lookup_var 逐级上溯)已存在同名变量, + # 优先按变量处理,跳过跨模块 CDefine 查找——否则 ALL_CAPS + # 命中 star-import 模块(from stdint import *)→ 无谓读源 + # 文件,且多 includes 目录下还可能触发 XMOD-CD 误报 + # (ExprGenCdef._build_source_path_from_sha1 拼错路径)。 + if self.Gen.VarGen.lookup_var(trans.SymTab, nm_id) is None: + cdef_val: t.CInt64T = self.Gen.ExprGenCdef._lookup_cross_module_cdefine( + pool, nm_id, trans._from_imports, trans._imported_modules, 0, node) + if self.Gen.TypeGenCDef.is_cdefine_found() != 0: + if self.Gen.TypeGenCDef.is_cdefine_str() != 0: + cdef_sv2: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id) + if cdef_sv2 is not None: + return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_sv2, trans) + self.Gen.TypeGenErr.fatal_error(node, f"CDefine 字符串值缺失: {nm_id}", "InternalCompilerError") + # 跨模块浮点 CDefine 已缓存为 double(is_cdefine_double), + # 需返回浮点常量而非截断的整数 + dchk_nm: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id) + if self.Gen.TypeGenCDef.is_cdefine_double() != 0: + return llvmlite.ConstFloat(pool, llvmlite.Double(pool), dchk_nm) + return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val) # CDefine 查找失败:from-import 的模块级全局变量(如 # from Phase1 import PYI_BUF_SIZE;PYI_BUF_SIZE: t.CSizeT = 262144 是 @@ -632,6 +640,33 @@ class ExprGenName(ExprGenBase.ExprGenBase): if idx_val is None: return None + # 嵌套下标读取: a[i][j] —— 递归取内层指针后 load + # (与 get_subscript_ptr 嵌套分支对称;如 gfx.vp 的 + # a.m[i][k] * b.m[k][j],内层 translate_value 会把行加载为 + # Array 值(非指针)→ 通用路径失败 → "rhs 翻译失败") + if sub.value is not None and sub.value.kind() == ast.ASTKind.Subscript: + inner_ptr_r: llvmlite.Value | t.CPtr = self.get_subscript_ptr( + builder, pool, mod, sub.value, trans) + if inner_ptr_r is None or inner_ptr_r.Ty is None: + return None + inner_elem_r: llvmlite.LLVMType | t.CPtr = inner_ptr_r.Ty.Pointee + if inner_elem_r is None: + return None + match inner_elem_r: + case llvmlite.LLVMType.Array(arr_ie_r, _): + elem_ptr_r: llvmlite.Value | t.CPtr = llvmlite.build_gep_array( + builder, inner_elem_r, arr_ie_r, inner_ptr_r, + self._zext_index_to_i32(builder, idx_val)) + if elem_ptr_r is not None: + return llvmlite.build_load(builder, arr_ie_r, elem_ptr_r) + return None + case _: + elem_ptr_r2: llvmlite.Value | t.CPtr = llvmlite.build_gep( + builder, inner_elem_r, inner_ptr_r, idx_val) + if elem_ptr_r2 is not None: + return llvmlite.build_load(builder, inner_elem_r, elem_ptr_r2) + return None + # 如果 value 是 Name,尝试从 alloca 类型推断 if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) @@ -912,6 +947,27 @@ class ExprGenName(ExprGenBase.ExprGenBase): if idx_val is None: return None + # 嵌套下标: a[i][j] = v —— 递归解析内层下标指针后 GEP + # (如 gfx.vp Mat4.m: t.CArray[t.CArray[float, 4], 4] 的 m.m[0][0] = 1; + # 外层 Subscript 的 value 是内层 Subscript,通用路径 translate_value + # 会把内层元素加载为值(Array 类型)→ is_ptr_type 失败 → 返回 None → + # "subscript ptr is None" fail-fast。递归取内层指针再 GEP 根治。) + if sub.value is not None and sub.value.kind() == ast.ASTKind.Subscript: + inner_ptr: llvmlite.Value | t.CPtr = self.get_subscript_ptr( + builder, pool, mod, sub.value, trans) + if inner_ptr is None or inner_ptr.Ty is None: + return None + inner_elem: llvmlite.LLVMType | t.CPtr = inner_ptr.Ty.Pointee + if inner_elem is None: + return None + match inner_elem: + case llvmlite.LLVMType.Array(arr_ie, _): + return llvmlite.build_gep_array( + builder, inner_elem, arr_ie, inner_ptr, + self._zext_index_to_i32(builder, idx_val)) + case _: + return llvmlite.build_gep(builder, inner_elem, inner_ptr, idx_val) + # 如果 value 是 Name,尝试从 alloca 类型推断 if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) diff --git a/App/lib/core/Gen/StmtGenCifMixin.vp b/App/lib/core/Gen/StmtGenCifMixin.vp index 4ebd74b..41e073a 100644 --- a/App/lib/core/Gen/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/StmtGenCifMixin.vp @@ -1211,10 +1211,20 @@ class StmtGenCifMixin: step_neg_const = 1 # 4. 创建/查找循环变量 alloca - var_alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var( + # 必须用 lookup_current(仅当前作用域):闭包内 lookup_var 会跨函数 + # 命中父函数同名变量(如父函数自己的循环计数器 i)→ 循环计数写到 + # 父函数存储 → 跨函数 SSA 错乱(llc "instruction expected to be + # numbered",Terminal _cmd_cd 的 for i in range(1,64) 根因)。 + var_alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_current( trans.SymTab, var_name) new_vars: int = 0 if var_alloca is None: + # 用 _alloca_at_entry:alloca 放函数入口块,保证支配性 + # (内联 build_alloca 若 preheader 是分支块(如 if.then), + # 循环三块跨块使用 → llc "Instruction does not dominate all + # uses!",Terminal _cmd_cd 的 for i in range(1,64) 根因)。 + # 闭包跨函数命中父函数变量的根因已由 lookup_current 修复, + # 故 entry 插入路径安全。 var_alloca = self.Gen.VarGen._alloca_at_entry(builder, i32_ty) if self.Gen.VarGen.define_var( trans.SymTab, var_name, var_alloca) == 0: