fix(gen): Gargantua 编译修复——循环 alloca 入入口块 + 跨模块 CDefine 拼路径/门控
- translate_for 循环计数 alloca 改回 _alloca_at_entry(入口块生成), 修复分支内 for 循环(Terminal _cmd_cd 的 for i in range(1,64))产生 "Instruction does not dominate all uses! %197 = alloca i32" - _build_source_path_from_sha1 优先用条目存储的 IncDir(绝对 includes 根, 多目录支持)拼路径,修复 Gargantua 多 includes 目录下 stdint.vp 拼到 首目录 ViperOS → 文件不存在 → XMOD-CD 误报 - translate_name_value 对 ALL_CAPS 名先查 lookup_var:当前作用域已有 同名变量(如 Gargantua CAM/FWD/RIGHT/UP 模块全局)则跳过跨模块 CDefine 查找,避免 star-import 误命中 stdint
This commit is contained in:
1 parent
bd3705d68b
commit
f2bfe82834
3 files changed
+99
-22
No files matched your search
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user