Files
Viper_VRTE/mlirlite/__init__.vp
T
TermiNexus c0d56b127d chore(comments): includes 头注释英文化(R11 收尾)
把 includes 下 64 个 .vp 的文件头注释(含 traceback.vp 第 13-427 行的整块文件级说明)以及 2 处漏网的正文中文注释(ast/lexer.vp、json/__writer.vp)与 1 处中文 docstring(memhub.vp)逐行译为英文;同步把 fltk/gen_ffi.py 的生成模板与其自身注释英文化,使重新生成仍为英文。

只改注释/文档串文字:行数与代码逐字节不变(骨架比对 140 文件漂移 0),运行时中文字符串字面量 305 处保持原样。验证:三重重编 SUCCESS(170.21s)+ 全量 77/77 顺序回归通过 + VET 编译 SUCCESS / --search-paths 7 条 exit 0。
2026-10-06 09:42:25 +08:00

462 lines
19 KiB
Plaintext

import t, c
from stdint import *
import memhub
import string
import viperlib
# ============================================================
# mlirlite -- an MLIR (llvm dialect) text emission library, isomorphic to llvmlite name for name
#
# Design principles:
# * The internal model (LLVMType/Value/Function/BasicBlock/IRBuilder/Module...) is
# **isomorphic to includes/llvmlite name for name and signature for signature**, so on the TPV side it suffices to rename
# `llvmlite.` to `mlirlite.` in order to compile;
# * The difference lies only in the "printing" stage: TypePrint / ValuePrint / FunctionPrint /
# LLVMModulePrint emit MLIR text, while the builders still generate the intermediate instruction text as before;
# * Names keep the LLVMxxx form (isomorphism first). See README.md for semantic differences.
# ============================================================
# Import submodules
from .__types import (
LLVMType, ParamNode, LLVMTypeCore,
Int1, Int8, Int16, Int32, Int64, Ptr, Func, Void, Array, Struct,
Half, Float, Double, FP128, Label,
new_param_node, param_list_append,
paramnode_get_ty, paramnode_get_next, paramnode_set_ty, paramnode_set_next,
TypePrint, PrintStructDefinition, get_struct_name,
get_struct_fields, get_struct_fcount, DeepCopyType,
)
from .__values import (
Value, new_value, ConstInt, ConstNull, ConstZero, ConstFloat, SSAValue, ValuePrint,
value_get_ty, value_get_next,
value_set_ty, value_set_next, value_set_name, value_set_isconst,
)
from .__function import (
Line, BasicBlock, Param, Function,
new_line, new_basic_block, new_param, new_function,
function_add_param, function_add_block,
block_append_line, block_append_text,
function_set_attrs, param_set_attrs,
function_set_attr_group,
function_set_dbg,
function_get_name, function_get_name_len, function_get_ret_ty, function_get_params,
function_get_param_head, function_get_next, function_is_declared,
param_get_name, param_get_ty, param_get_next,
FunctionPrint, G_PeepEnable,
DebugSetEnabled, DebugIsEnabled, DebugNoteFunc, DebugClearFunc,
DebugNoteLine, DebugResetFunc, DebugTakeText,
)
from .__module import (
LLVMModule, GlobalVariable, NamedTypeNode, DINode, DINamedMeta,
new_module, new_global_variable,
module_add_function, module_add_global, module_add_named_type,
module_set_named_type_packed,
module_set_target, module_set_datalayout,
module_add_di_node, module_add_named_metadata,
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
module_ensure_opaque_for_type,
)
from .__builder import (
IRBuilder, new_builder, position_at_end,
builder_cur_block_is_terminated,
builder_set_debug_location, builder_clear_debug_location,
build_alloca, build_alloca_aligned, build_alloca_at_entry, build_load, build_store,
build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem,
build_and, build_or, build_xor, build_shl, build_lshr, build_ashr,
build_fadd, build_fsub, build_fmul, build_fdiv, build_frem, build_fneg,
build_icmp, build_fcmp,
build_br, build_cond_br, build_ret, build_ret_void,
build_call, build_call_indirect, build_bitcast, build_sext, build_trunc, build_zext,
build_ptrtoint, build_inttoptr,
build_fpext, build_fptrunc, build_fp2si, build_si2fp, build_fp2ui, build_ui2fp,
build_gep, build_gep_array, build_gep_struct,
build_phi, build_switch, build_select, build_unreachable,
build_atomicrmw, build_cmpxchg, build_inline_asm, build_va_arg,
PhiIncoming, new_phi_incoming, SwitchCase, new_switch_case,
ICMP_EQ, ICMP_NE, ICMP_SGT, ICMP_SGE, ICMP_SLT, ICMP_SLE,
ICMP_UGT, ICMP_UGE, ICMP_ULT, ICMP_ULE,
FCMP_FALSE, FCMP_OEQ, FCMP_OGT, FCMP_OGE, FCMP_OLT, FCMP_OLE,
FCMP_ONE, FCMP_ORD, FCMP_UNO, FCMP_UEQ, FCMP_UGT, FCMP_UGE,
FCMP_ULT, FCMP_ULE, FCMP_UNE, FCMP_TRUE,
ATOMIC_XCHG, ATOMIC_ADD, ATOMIC_SUB, ATOMIC_AND, ATOMIC_NAND,
ATOMIC_OR, ATOMIC_XOR, ATOMIC_MAX, ATOMIC_MIN, ATOMIC_UMAX, ATOMIC_UMIN,
ATOMIC_ORDER_NOTATOMIC, ATOMIC_ORDER_UNORDERED, ATOMIC_ORDER_MONOTONIC,
ATOMIC_ORDER_ACQUIRE, ATOMIC_ORDER_RELEASE, ATOMIC_ORDER_ACQ_REL,
ATOMIC_ORDER_SEQ_CST,
)
from .__verify import (
VerifyResult, NameEntry,
verify_function, verify_module,
VERIFY_OK, VERIFY_ERR_NO_TERMINATOR, VERIFY_ERR_DUPLICATE_DEF,
VERIFY_ERR_UNDEFINED_USE, VERIFY_ERR_PHI_NOT_FIRST,
_new_verify_result,
)
# ============================================================
# Convenience factory: string copy
# ============================================================
def _str_dup(pool: memhub.MemBuddy*, src: str) -> str:
"""Allocate from pool and copy a C string."""
if src is None: return None
slen: sizet = string.strlen(src)
buf: str = pool.alloc(slen + 1)
if buf is None: return None
string.strcpy(buf, src)
return buf
# ============================================================
# Convenience factory: create a named basic block
# ============================================================
def create_block(pool: memhub.MemBuddy*, func: Function*,
name: str) -> BasicBlock*:
"""Create a basic block and add it to the function."""
# Block-name/param conflict guard: block label "entry:" is value %entry, so a param %entry
# collides; on collision append .1/.2/... (strip a leading % from Param.Name before comparing).
use_name: str = name
if func is not None and func.Params is not None and name is not None \
and name[0] != '\0':
cb_len: sizet = string.strlen(name) + 16
cb_buf: str = pool.alloc(cb_len)
if cb_buf is not None:
cb_k: int = 1
cb_collide: int = 1
while cb_collide != 0:
cb_collide = 0
cb_p: Param* = function_get_param_head(func)
while cb_p is not None:
cb_pnm: str = param_get_name(cb_p)
if cb_pnm is not None:
cb_pv: str = cb_pnm
if cb_pv[0] == '%':
cb_pv = cb_pv + 1
if string.strcmp(cb_pv, use_name) == 0:
cb_collide = 1
break
cb_p = param_get_next(cb_p)
if cb_collide != 0:
viperlib.snprintf(cb_buf, cb_len, "%s.%d", name, cb_k)
use_name = cb_buf
cb_k += 1
name_dup: str = _str_dup(pool, use_name)
blk: BasicBlock* = new_basic_block(pool, name_dup)
if blk is not None:
function_add_block(func, blk)
return blk
# ============================================================
# Convenience factory: create an integer constant value
# ============================================================
def const_int(pool: memhub.MemBuddy*, bits: int,
val: int64) -> Value*:
"""Create an integer constant value (auto-creates type + name text).
bits: bit width (1/8/16/32/64); val: integer value.
"""
# create type
ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
# create name text
name: str = pool.alloc(32)
if name is None: return None
# LLVM i64 literals exclude INT64_MIN: represent it as the unsigned bit pattern
# 9223372036854775808 (accepted by LLVM), else opt rejects "-9223372036854775808".
if bits == 64 and val == -9223372036854775807 - 1:
viperlib.snprintf(name, 32, "9223372036854775808")
else:
viperlib.snprintf(name, 32, "%lld", val)
return ConstInt(pool, ty, val, name)
def const_int32(pool: memhub.MemBuddy*, val: int64) -> Value*:
"""Convenience: create an i32 integer constant."""
return const_int(pool, 32, val)
def const_int64(pool: memhub.MemBuddy*, val: int64) -> Value*:
"""Convenience: create an i64 integer constant."""
return const_int(pool, 64, val)
# ============================================================
# Convenience factory: create a function and add it to the module
# ============================================================
def create_function(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, ret_ty: LLVMType*) -> Function*:
"""Create a function and add it to the module."""
name_dup: str = _str_dup(pool, name)
func: Function* = new_function(pool, name_dup, ret_ty)
if func is not None:
module_add_function(mod, func)
return func
def add_param(pool: memhub.MemBuddy*, func: Function*,
ty: LLVMType*, name: str) -> Param*:
"""Create a parameter and add it to the function."""
name_dup: str = _str_dup(pool, name)
param: Param* = new_param(pool, ty, name_dup)
if param is not None:
function_add_param(func, param)
return param
# ============================================================
# Convenience factory: create a function declaration (declare)
# ============================================================
def create_declare(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, ret_ty: LLVMType*) -> Function*:
"""Create a function declaration (declare, no body) and add it to the module.
Unlike create_function, it emits only: declare <ret_ty> @<name>(<params>)
"""
name_dup: str = _str_dup(pool, name)
func: Function* = new_function(pool, name_dup, ret_ty)
if func is not None:
func.IsDeclared = 1
module_add_function(mod, func)
return func
# ============================================================
# Convenience factory: create a string-constant global variable
#
# The initializer is stored in gv.Initializer as llvmlite-shaped LLVM syntax text (c"contents\00");
# the MLIR render stage (__module.vp/_MlirGlobalInit) converts it to the attribute form "contents".
# ============================================================
def create_global_string(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, text: str) -> GlobalVariable*:
"""Create a string-constant global variable and add it to the module.
name: global name (e.g. ".str"); text: C string without trailing NUL (added automatically).
Returns: GlobalVariable pointer of type [len+1 x i8].
"""
if text is None: return None
slen: sizet = string.strlen(text)
count: int = slen + 1 # includes the trailing NUL
# create i8 type
i8_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if i8_ty is None: return None
string.memset(i8_ty, 0, LLVMType.__sizeof__())
c.DerefAs(i8_ty, LLVMType.Int(8))
# create [count x i8] array type
arr_ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if arr_ty is None: return None
string.memset(arr_ty, 0, LLVMType.__sizeof__())
c.DerefAs(arr_ty, LLVMType.Array(i8_ty, count))
# create global variable
name_dup: str = _str_dup(pool, name)
gv: GlobalVariable* = new_global_variable(pool, name_dup, arr_ty)
if gv is None: return None
# set attributes: private + unnamed_addr + constant
global_set_linkage(gv, "private")
global_set_unnamed_addr(gv, 1)
global_set_constant(gv, 1)
# Build initializer text c"contents\00": LLVM IR string literal c"<chars>" with " \ and
# non-printables escaped as \xx; buffer sized for worst case (4 bytes/char) + c"..." + \00 + "
init_buf: str = pool.alloc(slen * 4 + 8)
if init_buf is None: return None
pos: sizet = 0
init_buf[pos] = 'c'
pos += 1
init_buf[pos] = '"'
pos += 1
for i in range(slen):
ch: uint8 = text[i]
if ch == 0x22 or ch == 0x5C or ch < 0x20 or ch >= 0x7F:
# escape: " -> \22, \ -> \5c, non-printable -> \xx
init_buf[pos] = '\\'
pos += 1
hi: int = (ch >> 4) & 0x0F
lo: int = ch & 0x0F
if hi < 10:
init_buf[pos] = 0x30 + hi
else:
init_buf[pos] = 0x61 + hi - 10
pos += 1
if lo < 10:
init_buf[pos] = 0x30 + lo
else:
init_buf[pos] = 0x61 + lo - 10
pos += 1
else:
init_buf[pos] = ch
pos += 1
# trailing NUL byte
init_buf[pos] = '\\'
pos += 1
init_buf[pos] = '0'
pos += 1
init_buf[pos] = '0'
pos += 1
init_buf[pos] = '"'
pos += 1
init_buf[pos] = '\0'
gv.Initializer = init_buf
module_add_global(mod, gv)
return gv
# ============================================================
# Convenience factory: create an integer global with an initializer
# ============================================================
def create_global_int(pool: memhub.MemBuddy*, mod: LLVMModule*,
name: str, bits: int, val: int64) -> GlobalVariable*:
"""Create an integer global variable and add it to the module.
MLIR output: llvm.mlir.global @<name>(<val> : i<bits>) : i<bits>
"""
# create integer type
ty: LLVMType* = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
name_dup: str = _str_dup(pool, name)
gv: GlobalVariable* = new_global_variable(pool, name_dup, ty)
if gv is None: return None
# build initializer text "42" (the type is printed separately by the global render stage)
init_buf: str = pool.alloc(48)
if init_buf is None: return None
viperlib.snprintf(init_buf, 48, "%lld", val)
gv.Initializer = init_buf
module_add_global(mod, gv)
return gv
# ============================================================
# LLVMModuleCore: module/function/value creation core; wraps pool to avoid passing it repeatedly
#
# Usage:
# mcore: rawptr[LLVMModuleCore] = LLVMModuleCore(pool)
# mod: rawptr[LLVMModule] = mcore.NewModule("test")
# func: rawptr[Function] = mcore.CreateFunction(mod, "add", ty_i32)
# val: rawptr[Value] = mcore.ConstInt32(42)
# ============================================================
@t.NoVTable
class LLVMModuleCore:
"""Module/function/value creation core; wraps pool so callers need not pass it."""
Pool: memhub.MemBuddy*
def __init__(self, pool: memhub.MemBuddy*):
self.Pool = pool
# ---- module operations ----
def NewModule(self, name: str) -> LLVMModule*:
return new_module(self.Pool, name)
def CreateFunction(self, mod: LLVMModule*, name: str,
ret_ty: LLVMType*) -> Function*:
return create_function(self.Pool, mod, name, ret_ty)
def CreateDeclare(self, mod: LLVMModule*, name: str,
ret_ty: LLVMType*) -> Function*:
"""Create a function declaration (declare, no body)."""
return create_declare(self.Pool, mod, name, ret_ty)
def AddParam(self, func: Function*, ty: LLVMType*,
name: str) -> Param*:
return add_param(self.Pool, func, ty, name)
def FunctionSetAttrs(self, func: Function*, attrs: str):
"""Set the function-level attribute text."""
function_set_attrs(func, attrs)
def ParamSetAttrs(self, param: Param*, attrs: str):
"""Set the parameter attribute text."""
param_set_attrs(param, attrs)
def CreateBlock(self, func: Function*,
name: str) -> BasicBlock*:
return create_block(self.Pool, func, name)
def NewBuilder(self, func: Function*) -> IRBuilder*:
return new_builder(self.Pool, func)
# ---- globals ----
def NewGlobal(self, mod: LLVMModule*, name: str,
ty: LLVMType*) -> GlobalVariable*:
"""Create a global variable and add it to the module."""
name_dup: str = _str_dup(self.Pool, name)
gv: GlobalVariable* = new_global_variable(self.Pool, name_dup, ty)
if gv is not None:
module_add_global(mod, gv)
return gv
def CreateGlobalString(self, mod: LLVMModule*, name: str,
text: str) -> GlobalVariable*:
"""Create a string-constant global variable."""
return create_global_string(self.Pool, mod, name, text)
def CreateGlobalInt(self, mod: LLVMModule*, name: str,
bits: int, val: int64) -> GlobalVariable*:
"""Create an integer global with an initializer."""
return create_global_int(self.Pool, mod, name, bits, val)
def GlobalSetConstant(self, gv: GlobalVariable*, is_const: int):
global_set_constant(gv, is_const)
def GlobalSetLinkage(self, gv: GlobalVariable*, linkage: str):
global_set_linkage(gv, linkage)
def GlobalSetUnnamedAddr(self, gv: GlobalVariable*, level: int):
global_set_unnamed_addr(gv, level)
def GlobalSetSection(self, gv: GlobalVariable*, section: str):
global_set_section(gv, section)
# ---- value creation ----
def ConstInt(self, bits: int, val: int64) -> Value*:
return const_int(self.Pool, bits, val)
def ConstInt32(self, val: int64) -> Value*:
return const_int32(self.Pool, val)
def ConstInt64(self, val: int64) -> Value*:
return const_int64(self.Pool, val)
def ConstFloat(self, ty: LLVMType*, val: double) -> Value*:
return ConstFloat(self.Pool, ty, val)
def SSAValue(self, ty: LLVMType*, name: str) -> Value*:
return SSAValue(self.Pool, ty, name)
def ConstNull(self, ty: LLVMType*, name: str) -> Value*:
return ConstNull(self.Pool, ty, name)
# ---- printing ----
def PrintValue(self, buf: str, size: sizet, val: Value*):
ValuePrint(buf, size, val, self.Pool)
def PrintFunction(self, buf: str, size: sizet, func: Function*):
FunctionPrint(buf, size, func, self.Pool)
def PrintModule(self, buf: str, size: sizet, mod: LLVMModule*):
LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL)
# ---- SSA verification ----
def NewVerifyResult(self, buf_size: sizet) -> VerifyResult*:
"""Create a verify-result object (buf_size = error message buffer size)."""
return _new_verify_result(self.Pool, buf_size)
def VerifyFunction(self, func: Function*,
result: VerifyResult*) -> int:
"""Verify SSA correctness of one function; returns error count (0 = pass)."""
return verify_function(self.Pool, func, result)
def VerifyModule(self, mod: LLVMModule*,
result: VerifyResult*) -> int:
"""Verify SSA correctness of all functions in the module; returns error count (0 = pass)."""
return verify_module(self.Pool, mod, result)