263 lines
8.5 KiB
Python
263 lines
8.5 KiB
Python
import t, c
|
||
from stdint import *
|
||
import string
|
||
import viperlib
|
||
import memhub
|
||
import hashtable
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
|
||
|
||
# ============================================================
|
||
# TypeKind - 类型种类枚举
|
||
#
|
||
# 替代 TransPyC 中 CType.position frozenset 的元属性系统。
|
||
# 每个 TypeInfo 通过 Kind 字段标记其种类,避免 Python ClassVar 反射。
|
||
# ============================================================
|
||
class TypeKind(t.CEnum):
|
||
Basic: t.State # 基本类型(int/char/float/double/bool 等)
|
||
Pointer: t.State # 指针(T*)— 指针层数由 TypeInfo.PtrCount 表达
|
||
Struct: t.State # 结构体/类
|
||
Union: t.State # 联合体
|
||
Enum: t.State # 枚举
|
||
Typedef: t.State # 类型别名
|
||
Function: t.State # 函数指针
|
||
Array: t.State # 数组 T[N]
|
||
Void: t.State # void
|
||
|
||
|
||
# ============================================================
|
||
# TypeInfo - 类型信息结构
|
||
#
|
||
# 设计原则(相对 TransPyC CTypeInfo 的简化):
|
||
# - POD 数据结构,无虚函数,无 Python 元特性(ClassVar/Generic/frozenset)
|
||
# - 通过 mbuddy 分配,调用方管理生命周期(参考 llvmlite Module 模式)
|
||
# - 通过 Kind 枚举代替 position frozenset
|
||
# - PtrCount 表达指针层数(0=非指针, 1=T*, 2=T**)
|
||
# - IsSigned 三态:-1=不适用(void/float), 0=unsigned, 1=signed
|
||
#
|
||
# 字段布局(8 字段):
|
||
# Kind : i32 类型种类(TypeKind 枚举值)
|
||
# Name : i8* 类型名(如 'int', 'CInt', 'MyStruct'),可能为 None
|
||
# Size : i32 位宽(0=void/未知;int=32, char=8, double=64, long long=64)
|
||
# Align : i32 对齐字节数(0=默认)
|
||
# IsSigned : i32 -1=N/A, 0=unsigned, 1=signed
|
||
# PtrCount : i32 指针层数
|
||
# IsConst : i32 const 限定符(0/1)
|
||
# IsVolatile : i32 volatile 限定符(0/1)
|
||
#
|
||
# 注意:Size 使用位宽(bit width)而非字节数,与 LLVM IR 的 i{N} 和
|
||
# TransPyC CType.Size 约定一致(CInt.Size=32, CChar.Size=8)。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class TypeInfo:
|
||
Kind: int
|
||
Name: str
|
||
Size: int
|
||
Align: int
|
||
IsSigned: int
|
||
PtrCount: int
|
||
IsConst: int
|
||
IsVolatile: int
|
||
|
||
|
||
# ============================================================
|
||
# TypeRegistry - 类型注册表
|
||
#
|
||
# 维护 name(str) → TypeInfo* 映射,基于 HashTable 实现 O(1) 查找。
|
||
# 替代 TransPyC CTypeRegistry 的 _name_to_class dict。
|
||
# 内置基本类型(int/char/void/...)由 InitBasicTypes 注册。
|
||
# ============================================================
|
||
class TypeRegistry:
|
||
_ht: hashtable.HashTable | t.CPtr
|
||
__mbuddy__: memhub.MemManager | t.CPtr
|
||
|
||
def Register(self, ti: TypeInfo | t.CPtr) -> int:
|
||
"""注册一个 TypeInfo。ti.Name 字段必须已设置。
|
||
|
||
Returns:
|
||
1 表示成功,0 表示失败(ti 为 None 或 Name 为 None)
|
||
"""
|
||
if ti is None:
|
||
return 0
|
||
if ti.Name is None:
|
||
return 0
|
||
self._ht[ti.Name] = ti
|
||
return 1
|
||
|
||
def Lookup(self, name: str) -> TypeInfo | t.CPtr:
|
||
"""按名称查找 TypeInfo。
|
||
|
||
Returns:
|
||
找到返回 TypeInfo*,找不到返回 None
|
||
"""
|
||
if name is None:
|
||
return None
|
||
return self._ht[name]
|
||
|
||
def Has(self, name: str) -> int:
|
||
"""检查类型是否已注册。"""
|
||
if name is None:
|
||
return 0
|
||
return name in self._ht
|
||
|
||
|
||
# ============================================================
|
||
# NewTypeInfo - 工厂函数:分配并初始化一个 TypeInfo
|
||
#
|
||
# 默认值:Kind=Basic, IsSigned=-1, 其余=0/None
|
||
# ============================================================
|
||
def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr:
|
||
ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__())
|
||
if ptr is None:
|
||
return None
|
||
string.memset(ptr, 0, TypeInfo.__sizeof__())
|
||
ptr.Kind = TypeKind.Basic
|
||
ptr.IsSigned = -1
|
||
return ptr
|
||
|
||
|
||
# ============================================================
|
||
# NewTypeRegistry - 工厂函数:创建类型注册表
|
||
# ============================================================
|
||
def NewTypeRegistry(pool: memhub.MemManager | t.CPtr) -> TypeRegistry | t.CPtr:
|
||
ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__())
|
||
if ptr is None:
|
||
return None
|
||
string.memset(ptr, 0, TypeRegistry.__sizeof__())
|
||
ptr.__mbuddy__ = pool
|
||
ptr._ht = hashtable.HashTable(pool)
|
||
return ptr
|
||
|
||
|
||
# ============================================================
|
||
# TypeToLLVM - 将 TypeInfo 转换为 LLVM IR 类型字符串
|
||
#
|
||
# 规则:
|
||
# - Kind == Void 或 (Size==0 且 IsSigned==-1 且 PtrCount==0) → "void"
|
||
# - void 有 PtrCount > 0 → "i8" + PtrCount 个 "*"
|
||
# - IsSigned == -1 且 Size > 0 → 浮点: half/float/double/fp128
|
||
# - IsSigned != -1 且 Size > 0 → 整数: i{Size}
|
||
# - 未知 → "i8*"
|
||
#
|
||
# Args:
|
||
# buf: 输出缓冲区(i8*)
|
||
# buf_size: 缓冲区容量
|
||
# ti: TypeInfo 指针
|
||
#
|
||
# Returns:
|
||
# 写入的字符数(不含 NUL),失败返回 -1
|
||
# ============================================================
|
||
def TypeToLLVM(buf: t.CChar | t.CPtr, buf_size: t.CSizeT,
|
||
ti: TypeInfo | t.CPtr) -> int:
|
||
if buf is None:
|
||
return -1
|
||
if ti is None:
|
||
return -1
|
||
if buf_size == 0:
|
||
return -1
|
||
|
||
# 判定 void
|
||
is_void: int = 0
|
||
if ti.Kind == TypeKind.Void:
|
||
is_void = 1
|
||
elif ti.Size == 0 and ti.IsSigned == -1 and ti.PtrCount == 0:
|
||
is_void = 1
|
||
|
||
# 写入 base 类型字符串到 buf
|
||
base_len: int = 0
|
||
if is_void == 1:
|
||
if ti.PtrCount == 0:
|
||
# "void"
|
||
if buf_size < 5:
|
||
return -1
|
||
string.strcpy(buf, "void")
|
||
base_len = 4
|
||
else:
|
||
# void* → i8*(LLVM 中 void* 表示为 i8*)
|
||
if buf_size < 4:
|
||
return -1
|
||
string.strcpy(buf, "i8")
|
||
base_len = 2
|
||
elif ti.IsSigned == -1:
|
||
# 浮点
|
||
if ti.Size == 16:
|
||
if buf_size < 5:
|
||
return -1
|
||
string.strcpy(buf, "half")
|
||
base_len = 4
|
||
elif ti.Size == 32:
|
||
if buf_size < 6:
|
||
return -1
|
||
string.strcpy(buf, "float")
|
||
base_len = 5
|
||
elif ti.Size == 64:
|
||
if buf_size < 7:
|
||
return -1
|
||
string.strcpy(buf, "double")
|
||
base_len = 6
|
||
elif ti.Size == 128:
|
||
if buf_size < 6:
|
||
return -1
|
||
string.strcpy(buf, "fp128")
|
||
base_len = 5
|
||
else:
|
||
# 未知浮点尺寸 → double 兜底
|
||
if buf_size < 7:
|
||
return -1
|
||
string.strcpy(buf, "double")
|
||
base_len = 6
|
||
else:
|
||
# 整数: i{Size},用 snprintf 安全写入
|
||
if ti.Size <= 0:
|
||
# 无效尺寸 → i8 兜底
|
||
if buf_size < 4:
|
||
return -1
|
||
string.strcpy(buf, "i8")
|
||
base_len = 2
|
||
else:
|
||
viperlib.snprintf(buf, buf_size, "i%d", ti.Size)
|
||
base_len = string.strlen(buf)
|
||
|
||
# 追加 PtrCount 个 "*"
|
||
if base_len + ti.PtrCount + 1 > buf_size:
|
||
return -1
|
||
pos: int = base_len
|
||
for i in range(ti.PtrCount):
|
||
buf[pos] = '*'
|
||
pos += 1
|
||
buf[pos] = 0
|
||
return pos
|
||
|
||
|
||
# ============================================================
|
||
# Mixin - 所有 Handle 的非多态基类(对应 TransPyC 的 BaseHandle)
|
||
#
|
||
# @t.NoVTable 继承:字段展平嵌入子类,无 vtable 开销(对应 C++ 非多态继承)。
|
||
# 子类继承 Trans 字段 + 共享工具方法,编译器自动生成子类方法包装
|
||
# (self bitcast 为父类指针后调用),子类可直接调用继承的方法。
|
||
#
|
||
# 用法:
|
||
# @t.NoVTable
|
||
# class AssignHandle(Mixin):
|
||
# _CurrentClass: str
|
||
# def __init__(self, trans):
|
||
# self.InitMixin(trans)
|
||
# self._CurrentClass = None
|
||
# def Handle(self, node) -> int:
|
||
# rhs = self.Trans.ExprH.HandleValue(node.value)
|
||
# ...
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class Mixin:
|
||
"""所有 Handle 的非多态基类:持有 Translator 回指针 + 共享委托方法"""
|
||
Trans: HT.Translator | t.CPtr
|
||
|
||
def InitMixin(self, trans: HT.Translator | t.CPtr) -> int:
|
||
"""初始化 Mixin 字段(子类 __init__ 中调用)"""
|
||
self.Trans = trans
|
||
return 0
|
||
|
||
|
||
# 全局 mbuddy 指针
|
||
_mbuddy: t.CVoid | t.CPtr
|