fix(cif): 平台宏按目标 triple 求值,属性形式不再依赖跨模块 define
- _cif_attr_value 先查平台内建宏(triple 是唯一真相源),再查本地/跨模块 DefineT: 跨模块查不到时会静默得到 0,曾把 platmacro.IS_WINDOWS 判成 0, 导致 Windows 构建误走非 Windows 分支(_io 选了 posix.fileio) - _get_platform_macro_value 补齐 platmacro 的平台名:IS_WINDOWS/IS_WIN64/IS_LINUX/ IS_MACOS/IS_X86_64/IS_ARM64 注:本文件含此前未提交的既有改动,按整文件一并提交。
This commit is contained in:
1 parent
3febb87abf
commit
da636a5422
1 file changed
+22
-9
@@ -88,10 +88,18 @@ novirtual class StmtGenCifMixin:
|
||||
if string.strcmp(name, "SIZEOF_VOID_P") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "__SIZEOF_POINTER__") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "NDEBUG") == 0: self.CifEvalOk = 1; return 0
|
||||
# platmacro.vp 的平台名(它是 includes/platmacro.vp 的手写镜像;cif 直接按 triple 求值,
|
||||
# 不依赖跨模块 define 解析——曾因跨模块查不到而静默取 0,误选了非 Windows 分支)。
|
||||
if string.strcmp(name, "IS_WINDOWS") == 0: self.CifEvalOk = 1; return is_win
|
||||
if string.strcmp(name, "IS_WIN64") == 0: self.CifEvalOk = 1; return is_win if is_x64 else 0
|
||||
if string.strcmp(name, "IS_LINUX") == 0: self.CifEvalOk = 1; return is_linux
|
||||
if string.strcmp(name, "IS_MACOS") == 0: self.CifEvalOk = 1; return 0
|
||||
if string.strcmp(name, "IS_X86_64") == 0: self.CifEvalOk = 1; return is_x64
|
||||
if string.strcmp(name, "IS_ARM64") == 0: self.CifEvalOk = 1; return 0
|
||||
return 0
|
||||
|
||||
def _cif_name_value(self, pool: memhub.MemBuddy*, trans: HT.Translator*, name: str) -> int:
|
||||
"""Resolve a macro name via local CDefine, cross-module CDefine, then platform macro."""
|
||||
"""Resolve a macro name via local DefineT, cross-module DefineT, then platform macro."""
|
||||
self.CifEvalOk = 0
|
||||
if name is None or trans is None: return 0
|
||||
v: int = int(self.Gen.TypeGenCDef.lookup_cdefine_constant(name))
|
||||
@@ -107,12 +115,17 @@ novirtual class StmtGenCifMixin:
|
||||
return 0
|
||||
|
||||
def _cif_attr_value(self, pool: memhub.MemBuddy*, trans: HT.Translator*, at: ast.Attribute*) -> int:
|
||||
"""Resolve an attribute macro via platform macro, local CDefine, then cross-module CDefine."""
|
||||
"""Resolve an attribute macro via platform macro, local DefineT, then cross-module DefineT."""
|
||||
self.CifEvalOk = 0
|
||||
if at is None or at.attr is None or at.value is None or trans is None: return 0
|
||||
if at.value.kind() != ast.ASTKind.Name: return 0
|
||||
vn: ast.Name* = ast.Name*(at.value)
|
||||
if vn.id is None: return 0
|
||||
# 平台内建宏优先:目标 triple 是唯一真相源(platmacro 只是它的手写照)。
|
||||
# 必须排在跨模块 define 之前——跨模块查不到时这里会静默拿到 0(曾把
|
||||
# platmacro.IS_WINDOWS 判成 0,导致 Windows 构建误选非 Windows 分支)。
|
||||
pv_at: int = self._get_platform_macro_value(at.attr)
|
||||
if self.CifEvalOk != 0: return pv_at
|
||||
v: int = int(self.Gen.TypeGenCDef.lookup_cdefine_constant(at.attr))
|
||||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||||
self.CifEvalOk = 1
|
||||
@@ -274,7 +287,7 @@ novirtual class StmtGenCifMixin:
|
||||
"""Evaluate the defined(NAME) compile-time predicate (1 = macro defined, 0 = not).
|
||||
|
||||
defined() is always evaluable: an unknown name yields 0. A wrong argument shape is fail-fast.
|
||||
The macro name resolves through the same CDefine / cross-module / platform-macro paths as a
|
||||
The macro name resolves through the same DefineT / cross-module / platform-macro paths as a
|
||||
bare name in a cif condition.
|
||||
"""
|
||||
cargs: list[ast.AST*]* = cl.args
|
||||
@@ -407,7 +420,7 @@ novirtual class StmtGenCifMixin:
|
||||
if self.CifEvalOk == 0:
|
||||
self.Gen.TypeGenErr.fatal_error(test,
|
||||
f"the cif/celif condition is not a compile-time constant (line {test.lineno}):"
|
||||
" cif/celif accept only CDefine constants, integer literals, defined(NAME), and their"
|
||||
" cif/celif accept only DefineT constants, integer literals, defined(NAME), and their"
|
||||
" constant arithmetic/comparison/boolean/bitwise combinations", "TypeError")
|
||||
return v
|
||||
|
||||
@@ -505,13 +518,13 @@ novirtual class StmtGenCifMixin:
|
||||
if cur_func_rv is not None: ret_val_ty = mlirlite.function_get_ret_ty(cur_func_rv)
|
||||
# `return <闭包变量>` 且返回注解是 t.Callable:闭包对象是 {fn_ptr, env_ptr},
|
||||
# 不是裸函数指针。调用方把结果存进 t.Callable 变量后 `f()` 会按裸函数指针直调,
|
||||
# 跳到堆地址崩溃(ClosureCallTest 现场)。这里明确 fail-fast,要求用 rawptr/t.CPtr。
|
||||
# 跳到堆地址崩溃(ClosureCallTest 现场)。这里明确 fail-fast,要求用 rawptr。
|
||||
if rt.value.kind() == ast.ASTKind.Name and trans is not None and trans.CurFuncRetAnnot is not None:
|
||||
clo_nm_rv: ast.Name* = ast.Name*(rt.value)
|
||||
if clo_nm_rv.id is not None and self.Gen.CallGenLeafKit.is_closure_name(clo_nm_rv.id) != 0:
|
||||
clo_ret_rv: mlirlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, trans.CurFuncRetAnnot, trans._imported_modules, trans._from_imports, trans)
|
||||
if clo_ret_rv is not None:
|
||||
self.Gen.TypeGenErr.fatal_error(rt, f"the return annotation is t.Callable (a bare function pointer) but the returned value is the closure variable '{clo_nm_rv.id}'. A closure is a (fn_ptr, env_ptr) object; storing it where a t.Callable is expected makes the caller jump into heap data. Annotate the return as rawptr / t.CPtr instead", "TypeError")
|
||||
self.Gen.TypeGenErr.fatal_error(rt, f"the return annotation is t.Callable (a bare function pointer) but the returned value is the closure variable '{clo_nm_rv.id}'. A closure is a (fn_ptr, env_ptr) object; storing it where a t.Callable is expected makes the caller jump into heap data. Annotate the return as rawptr instead", "TypeError")
|
||||
# [C1] return-annotation context: record this return's direct value node so a bare
|
||||
# generic ctor (`return Stack()` in `-> Stack[int]`) specializes via CurFuncRetAnnot.
|
||||
trans.CurRetNode = rt.value
|
||||
@@ -1063,7 +1076,7 @@ novirtual class StmtGenCifMixin:
|
||||
cn_ik: ast.Constant* = ast.Constant*(iter_node)
|
||||
if cn_ik.const_kind != ast.CONST_STR: self.Gen.TypeGenErr.fatal_error(iter_node, "for iteration does not support this constant (only strings, arrays, list literals, range())")
|
||||
elif ik == ast.ASTKind.Dict or ik == ast.ASTKind.Set or ik == ast.ASTKind.Tuple or ik == ast.ASTKind.SetComp or ik == ast.ASTKind.DictComp:
|
||||
self.Gen.TypeGenErr.fatal_error(iter_node, "for iteration does not support dict/set/tuple literals; use range(), a t.CArray array, or a list literal")
|
||||
self.Gen.TypeGenErr.fatal_error(iter_node, "for iteration does not support dict/set/tuple literals; use range(), a t.ArrayT array, or a list literal")
|
||||
return self._handle_ptr_iter(trans, for_node, var_name)
|
||||
|
||||
call: ast.Call* = ast.Call*(iter_node)
|
||||
@@ -1675,7 +1688,7 @@ novirtual class StmtGenCifMixin:
|
||||
elem_ty: mlirlite.LLVMType* = ptr_val.Ty.Pointee
|
||||
if elem_ty is None: self.Gen.TypeGenErr.fatal_error(for_node, "pointer iteration: failed to get the element type")
|
||||
|
||||
# element type is an array (Ptr([N x T]), e.g. a decayed t.CArray): load it and iterate by length (no null terminator)
|
||||
# element type is an array (Ptr([N x T]), e.g. a decayed t.ArrayT): load it and iterate by length (no null terminator)
|
||||
if self.Gen.ExprGenBase.is_array_type(elem_ty) != 0:
|
||||
arr_v2: mlirlite.Value* = mlirlite.build_load(builder, elem_ty, ptr_val)
|
||||
if arr_v2 is not None: return self._handle_array_iter(trans, for_node, var_name, arr_v2)
|
||||
@@ -1926,7 +1939,7 @@ novirtual class StmtGenCifMixin:
|
||||
# element count above the actual fill means a bare 0 slot, i.e. an empty AST element upstream.
|
||||
if first_el is None:
|
||||
self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an empty AST element: element 0 is a bare null pointer (0), " f"but the element count is {elts_count} (element and count mismatch); something upstream produced an empty AST element, compilation aborted.", "ValueError")
|
||||
# validate the object (vptr non-zero, see AssignGenMixin.vp:1174-1183): for @t.CVTable class
|
||||
# validate the object (vptr non-zero, see AssignGenMixin.vp:1174-1183): for @t.VTableT class
|
||||
# objects the first word is the vptr; if 0, any later virtual call reads address 0.
|
||||
if *((uint64*)(first_el)) == 0:
|
||||
self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an [INVALID OBJECT] AST element (vptr is 0): element 0 pointer is nonzero" f"(address {uint64(first_el)}) but the first word of its object (vtable pointer) is 0, element count {elts_count};" f"something upstream produced an [uninitialized vptr AST node] (typical source: a deep copy that moved fields but not the vptr), compilation aborted.", "ValueError")
|
||||
|
||||
Reference in new issue
Block a user