diff --git a/lib/core/LLVMCG/MemoryOps.py b/lib/core/LLVMCG/MemoryOps.py index 07003e6..40cc4b6 100644 --- a/lib/core/LLVMCG/MemoryOps.py +++ b/lib/core/LLVMCG/MemoryOps.py @@ -194,6 +194,11 @@ class MemoryOpsMixin: val = self.builder.zext(val, ir.IntType(64), name="zext_ptr_store") return self.builder.inttoptr(val, target_type, name="int_to_ptr_store") if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.PointerType): + if isinstance(val, ir.Constant) and val.constant is None: + # null 指针常量赋给 int 字段 → 0。绝不能对 null 做 load + # (此前 pointee.width == target.width 时直接 load null, + # 生成 `load i32, i32* null` → ASAN access-violation) + return ir.Constant(target_type, 0) if isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == target_type.width: return self.builder.load(val, name="load_ptr_as_int_store") if target_type.width <= 8 and isinstance(val.type.pointee, ir.IntType): @@ -264,6 +269,10 @@ class MemoryOpsMixin: elif isinstance(target_type, ir.IdentifiedStructType): val = ir.Constant(ir.PointerType(target_type), None) ptr = self.builder.bitcast(ptr, ir.PointerType(ir.PointerType(target_type)), name="null_struct_ptr_cast") + elif isinstance(target_type, ir.IntType): + # null 指针常量赋给 int 字段 → 0(与 _coerce_value 一致, + # 防止 `store i32* null, i32*` 类型错乱 IR) + val = ir.Constant(target_type, 0) else: coerced: ir.Value | None = self._coerce_value(val, target_type) if coerced is not None: