213 lines
6.5 KiB
Python
213 lines
6.5 KiB
Python
import t, c
|
||
from stdint import *
|
||
import string
|
||
import viperlib
|
||
import memhub
|
||
from linkedlist import GSListNode
|
||
from .__types import LLVMType, TypePrint
|
||
|
||
|
||
# ============================================================
|
||
# Value: SSA 值表示
|
||
#
|
||
# 表示一个 LLVM IR 值:SSA 临时值(%0/%result)或常量字面量(42/0)。
|
||
# 每个值有类型指针、名字、是否常量标志。
|
||
# 继承 GSListNode[Value] 获取强类型 Next: Value|CPtr(值池链表)
|
||
# ============================================================
|
||
class Value(GSListNode[Value]):
|
||
Ty: LLVMType | t.CPtr # 值的类型
|
||
Name: t.CChar | t.CPtr # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
|
||
IsConst: t.CInt # 1=常量字面量, 0=SSA 临时值
|
||
IntVal: t.CInt64T # 整数常量值(当 IsConst=1 时使用)
|
||
FloatVal: t.CDouble # 浮点常量值(当 IsConst=1 且 Ty 为 Float 时使用)
|
||
|
||
|
||
# ============================================================
|
||
# 工厂函数
|
||
# ============================================================
|
||
# Value 硬编码大小: Next(8) + Ty(8) + Name(8) + IsConst(4) + IntVal(8) + FloatVal(8) = 48 字节
|
||
VALUE_SIZE: t.CDefine = 48
|
||
|
||
def new_value(pool: memhub.MemBuddy | t.CPtr) -> Value | t.CPtr:
|
||
"""从 mpool 分配一个零初始化的 Value"""
|
||
ptr: Value | t.CPtr = pool.alloc(VALUE_SIZE)
|
||
if ptr:
|
||
string.memset(ptr, 0, VALUE_SIZE)
|
||
return ptr
|
||
|
||
|
||
def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
||
val: t.CInt64T, name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
||
"""创建整数常量值
|
||
|
||
参数:
|
||
ty: 整数类型(Int1/Int8/Int32/Int64)
|
||
val: 整数值
|
||
name: 常量文本(如 "42"),由调用方提供
|
||
"""
|
||
v: Value | t.CPtr = new_value(pool)
|
||
if v is None: return None
|
||
v.Ty = ty
|
||
v.Name = name
|
||
v.IsConst = 1
|
||
v.IntVal = val
|
||
return v
|
||
|
||
|
||
def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
||
name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
||
"""创建 null 指针常量"""
|
||
v: Value | t.CPtr = new_value(pool)
|
||
if v is None: return None
|
||
v.Ty = ty
|
||
v.Name = name
|
||
v.IsConst = 1
|
||
v.IntVal = 0
|
||
return v
|
||
|
||
|
||
def ConstZero(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Value | t.CPtr:
|
||
"""创建 zeroinitializer 常量(零初始化聚合类型:结构体/数组)"""
|
||
v: Value | t.CPtr = new_value(pool)
|
||
if v is None: return None
|
||
v.Ty = ty
|
||
v.Name = "zeroinitializer"
|
||
v.IsConst = 1
|
||
v.IntVal = 0
|
||
return v
|
||
|
||
|
||
def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
||
val: t.CDouble) -> Value | t.CPtr:
|
||
"""创建浮点常量值
|
||
|
||
参数:
|
||
ty: 浮点类型(Half/Float/Double/FP128)
|
||
val: 浮点数值
|
||
名字自动格式化为 LLVM IR 科学计数法文本(如 "1.500000e+00")。
|
||
"""
|
||
v: Value | t.CPtr = new_value(pool)
|
||
if v is None: return None
|
||
v.Ty = ty
|
||
v.IsConst = 1
|
||
v.FloatVal = val
|
||
v.IntVal = 0
|
||
# 格式化名字: LLVM IR 使用 "%e" 科学计数法(6 位小数)
|
||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||
if name_buf is not None:
|
||
viperlib.snprintf(name_buf, 32, "%e", val)
|
||
v.Name = name_buf
|
||
return v
|
||
|
||
|
||
def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
||
name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
||
"""创建 SSA 临时值
|
||
|
||
参数:
|
||
ty: 值类型
|
||
name: SSA 名(如 "%0"/"%result"),由调用方提供
|
||
"""
|
||
v: Value | t.CPtr = new_value(pool)
|
||
if v is None: return None
|
||
v.Ty = ty
|
||
v.Name = name
|
||
v.IsConst = 0
|
||
v.IntVal = 0
|
||
return v
|
||
|
||
|
||
# ============================================================
|
||
# ValuePrint: 将值序列化为 IR 文本
|
||
#
|
||
# 示例:
|
||
# ConstInt(i32, 42, "42") -> "i32 42"
|
||
# SSAValue(i32, "%0") -> "i32 %0"
|
||
# ============================================================
|
||
def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
||
val: Value | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
||
"""将值 val 序列化为 IR 文本写入 buf
|
||
|
||
格式: <type> <name>
|
||
pool 用于复杂类型(Array/Struct/Func)递归打印时分配临时缓冲区。
|
||
"""
|
||
if val is None or buf is None or size == 0:
|
||
return
|
||
# 先写类型
|
||
TypePrint(buf, size, val.Ty, pool)
|
||
# 追加空格
|
||
pos: t.CSizeT = string.strlen(buf)
|
||
if pos + 1 < size:
|
||
buf[pos] = ' '
|
||
buf[pos + 1] = '\0'
|
||
# 追加名字
|
||
if val.Name is not None:
|
||
pos = string.strlen(buf)
|
||
_append_str(buf, size, val.Name)
|
||
|
||
|
||
# ============================================================
|
||
# Value 字段访问器(供其他模块绕过 stub 类型限制使用)
|
||
#
|
||
# 跨模块编译时,使用方模块只有 Value 的 stub 类型(字段不足或偏移错误),
|
||
# 导致 TransPyC 静默跳过字段访问(不生成 GEP,不报错)。
|
||
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问所有字段。
|
||
# ============================================================
|
||
def value_get_ty(val: Value | t.CPtr) -> LLVMType | t.CPtr:
|
||
"""获取值的类型"""
|
||
if val is None:
|
||
return None
|
||
return val.Ty
|
||
|
||
|
||
def value_get_next(val: Value | t.CPtr) -> Value | t.CPtr:
|
||
"""获取链表下一个值"""
|
||
if val is None:
|
||
return None
|
||
return val.Next
|
||
|
||
|
||
def value_set_ty(val: Value | t.CPtr, ty: LLVMType | t.CPtr):
|
||
"""设置值的类型"""
|
||
if val is None:
|
||
return
|
||
val.Ty = ty
|
||
|
||
|
||
def value_set_next(val: Value | t.CPtr, nxt: Value | t.CPtr):
|
||
"""设置链表下一个值"""
|
||
if val is None:
|
||
return
|
||
val.Next = nxt
|
||
|
||
|
||
def value_set_name(val: Value | t.CPtr, name: t.CChar | t.CPtr):
|
||
"""设置值的名字"""
|
||
if val is None:
|
||
return
|
||
val.Name = name
|
||
|
||
|
||
def value_set_isconst(val: Value | t.CPtr, is_const: t.CInt):
|
||
"""设置是否为常量"""
|
||
if val is None:
|
||
return
|
||
val.IsConst = is_const
|
||
|
||
|
||
# ============================================================
|
||
# 内部辅助
|
||
# ============================================================
|
||
def _append_str(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
|
||
"""将 src 追加到 dst 末尾"""
|
||
if dst is None or src is None: return
|
||
dlen: t.CSizeT = string.strlen(dst)
|
||
slen: t.CSizeT = string.strlen(src)
|
||
remain: t.CSizeT = dst_size - dlen
|
||
if remain <= 0: return
|
||
i: t.CSizeT = 0
|
||
while i < slen and i + 1 < remain:
|
||
dst[dlen + i] = src[i]
|
||
i += 1
|
||
dst[dlen + i] = '\0'
|