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 格式: 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'