Files
TransPyC/includes/llvmlite/__values.py

216 lines
6.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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值池链表
#
# 注意: 必须加 @t.NoVTable理由见 __function.py 的 Line 注释)。
# ============================================================
@t.NoVTable
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'