feat(cdef): define 常量带类型注册——按声明类型物化(DWORD(-11) → i32 位型)

方案 C:CDefine 不再只存无类型 int,而是把**声明整数类型**(位宽 + 符号性)一并登记,使用点按该类型物化,而不是按数值大小猜 i32/i64。链路:① SymbolUtils 新增 DefineIntSignednessOf / DefineDeclIntTypeFromAnnotation(由 T | t.CDefine 注解经符号表 typedef 链解析宽度与符号性)/ DefineDeclTypeValue(按声明类型把值归一成 (位宽, 位型值));② 同模块注册(LlvmGenerator._register_cdefine_constant)与跨模块提取(Phase2Translator._ExtractCDefineConstantsFromPyi,含 _shared_all_decl_types 的 pickle 传递)分别写 Gen._define_decl_types / translator._define_decl_types;③ 物化处(HandlesExpr 裸名两处、HandlesExprAttr._make_define_constant,及 from-import 注册)优先按声明类型出常量。这样 win32file 的 STD_*_HANDLE(DWORD(-10/-11/-12))解析为 i32 位型 0xFFFFFFF5 等,与 GetStdHandle(ULONG) 使用点一致。
This commit is contained in:
TermiNexus committed 2026-10-10 21:20:30 +08:00
1 parent e1a0fbf9c0
commit d5b4e9a8b9
6 files changed
+198 -20

No files matched your search

+12 -1
View File
@@ -9,7 +9,7 @@ import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle
from lib.constants.config import mode as _config_mode
from lib.includes.t import CTypeRegistry as _CR
from lib.core.SymbolUtils import RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined
from lib.core.SymbolUtils import RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined, DefineDeclTypeValue
# ---------------------------------------------------------------
@@ -455,6 +455,12 @@ class ExprHandle(BaseHandle):
RequireDefineUseWidthAt(Gen, self.Trans, Node, _cdefine_val,
int(_use_ty.width), VarName, _use_ctx)
return ir.Constant(_use_ty, val & ((1 << _use_ty.width) - 1))
# 带类型注册:无使用处宽度提示时,按 define 的**声明类型**物化
# (`define X: DWORD = -11` → i32 位型 0xFFFFFFF5,而不是按值大小猜 i64)。
_dtv: tuple[int, int] | None = DefineDeclTypeValue(
getattr(Gen, '_define_decl_types', None) or getattr(self.Trans, '_define_decl_types', None), VarName, val)
if _dtv is not None:
return ir.Constant(ir.IntType(_dtv[0]), _dtv[1])
if VarName in Gen.var_signedness and Gen.var_signedness[VarName]:
if val < -(1 << 31) or val > 0xFFFFFFFF:
return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF)
@@ -493,6 +499,11 @@ class ExprHandle(BaseHandle):
RequireDefineUseWidthAt(Gen, self.Trans, Node, val,
int(_use_ty2.width), VarName, _use_ctx2)
return ir.Constant(_use_ty2, val & ((1 << _use_ty2.width) - 1))
# 带类型注册:同本模块路径——按声明类型物化(见上)。
_dtv2: tuple[int, int] | None = DefineDeclTypeValue(
getattr(Gen, '_define_decl_types', None) or getattr(self.Trans, '_define_decl_types', None), VarName, val)
if _dtv2 is not None:
return ir.Constant(ir.IntType(_dtv2[0]), _dtv2[1])
if val < -(1 << 31) or val > 0xFFFFFFFF:
return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF)
return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF)
+17 -6
View File
@@ -5,6 +5,7 @@ if TYPE_CHECKING:
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta
from lib.core.VLogger import get_logger as _vlog
from lib.core.SymbolUtils import DefineDeclTypeValue
import vast as ast
import llvmlite.ir as ir
@@ -388,8 +389,18 @@ class ExprAttrHandle(BaseHandle):
return self._gep_and_Load_member(Gen, CastedObj, offset, Node.attr, lookup_CN, spec_st)
return None
def _make_define_constant(self, Gen: LlvmCodeGenerator, val: int | float | str) -> ir.Value | None:
"""将 CDefine 值转为 LLVM 常量"""
def _make_define_constant(self, Gen: LlvmCodeGenerator, val: int | float | str, Name: str | None = None) -> ir.Value | None:
"""将 CDefine 值转为 LLVM 常量。
带类型注册优先:若该 define 登记了**声明整数类型**(`Gen._define_decl_types`),
按该类型的位宽与符号性物化(u32 `DWORD(-11)` → `i32 0xFFFFFFF5`),而不是按
数值大小猜 i32/i64(后者会把 `4294967285` 误判成 i64,与 i32/ULONG 使用点不符)。
"""
if isinstance(val, int) and not isinstance(val, bool):
_dt: tuple[int, int] | None = DefineDeclTypeValue(
getattr(Gen, '_define_decl_types', None) or getattr(self.Trans, '_define_decl_types', None), Name, val)
if _dt is not None:
return ir.Constant(ir.IntType(_dt[0]), _dt[1])
if isinstance(val, int):
if abs(val) > 2147483647:
return ir.Constant(ir.IntType(64), val)
@@ -419,12 +430,12 @@ class ExprAttrHandle(BaseHandle):
for lookup_key in PossibleKeys:
SymInfo: Any = self.Trans.SymbolTable.lookup(lookup_key)
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
return self._make_define_constant(Gen, SymInfo.DefineValue)
return self._make_define_constant(Gen, SymInfo.DefineValue, AttrName)
# 也检查 _define_constants(LlvmGenerator 预扫描阶段填充)
define_constants: Any = getattr(Gen, '_define_constants', {})
for key in (f"{VarName}.{AttrName}", AttrName):
if key in define_constants:
return self._make_define_constant(Gen, define_constants[key])
return self._make_define_constant(Gen, define_constants[key], AttrName)
# 回退:_all_define_constants(Phase2Translator 从所有 .pyi 预提取的跨模块 CDefine,
# 与 _HandleNameLlvm 的裸名回退同源)。**模块属性访问**(`win32file.STD_OUTPUT_HANDLE`)
# 此前只查 SymbolTable/_define_constants → 未命中就落到 _lookup_module_global 生成
@@ -436,7 +447,7 @@ class ExprAttrHandle(BaseHandle):
all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {}
for key2 in (f"{VarName}.{AttrName}", AttrName):
if key2 in all_dc:
return self._make_define_constant(Gen, all_dc[key2])
return self._make_define_constant(Gen, all_dc[key2], AttrName)
return None
def _NormalizeModuleGlobalValue(self, Gen: LlvmCodeGenerator, Val: Any, AttrName: str) -> Any:
@@ -688,7 +699,7 @@ class ExprAttrHandle(BaseHandle):
for _cdefine_key in (AttrName, f"{VarName}.{AttrName}"):
_sym: Any = self.Trans.SymbolTable.lookup(_cdefine_key)
if _sym and _sym.IsDefine and _sym.DefineValue is not None:
_const_val: Any = self._make_define_constant(Gen, _sym.DefineValue)
_const_val: Any = self._make_define_constant(Gen, _sym.DefineValue, AttrName)
if _const_val is not None:
return _const_val
+7
View File
@@ -521,6 +521,13 @@ class ImportHandle(BaseHandle):
all_dc: dict = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {}
if name in all_dc:
define_constants[name] = all_dc[name]
# 带类型注册:把跨模块 define 的**声明整数类型**一并带入本模块,
# 供使用点按声明类型(如 DWORD=u32)物化,而不是按值大小猜 i32/i64。
all_dt: dict = getattr(Gen, '_define_decl_types', None) or getattr(self.Trans, '_define_decl_types', None) or {}
if name in all_dt:
_dt_map: dict = vars(Gen).setdefault('_define_decl_types', {})
if name not in _dt_map:
_dt_map[name] = all_dt[name]
continue
if not hasattr(self.Trans, '_t_c_imported_names'):
self.Trans._t_c_imported_names = {}