修正了一些错误

This commit is contained in:
2026-07-26 20:32:26 +08:00
parent ca7c2120b8
commit 1837339f69
203 changed files with 374300 additions and 2638 deletions

View File

@@ -3,6 +3,7 @@ from stdint import *
import string
import viperlib
import memhub
import stdio
from linkedlist import GSListNode, GSList
from .__types import LLVMType, TypePrint
from .__values import Value, new_value, SSAValue
@@ -145,6 +146,36 @@ def build_alloca(builder: IRBuilder | t.CPtr, ty: LLVMType | t.CPtr) -> Value |
return SSAValue(pool, result_ty_ptr, name)
def build_alloca_at_entry(builder: IRBuilder | t.CPtr, ty: LLVMType | t.CPtr) -> Value | t.CPtr:
"""%N = alloca <ty>(在函数入口块生成,确保支配性)
在入口块的终止指令之前插入 alloca避免在条件分支内生成 alloca
导致的支配性违规Instruction does not dominate all uses
"""
if builder is None: return None
pool: memhub.MemBuddy | t.CPtr = builder.Pool
func: Function | t.CPtr = builder.Func
if func is None or func.Blocks is None:
return build_alloca(builder, ty)
entry_blk: BasicBlock | t.CPtr = func.Blocks.Head
if entry_blk is None:
return build_alloca(builder, ty)
name: t.CChar | t.CPtr = _alloc_ssa_name(builder)
ty_s: t.CChar | t.CPtr = _type_str(builder, ty)
line_text: t.CChar | t.CPtr = pool.alloc(128)
if line_text is None: return None
viperlib.snprintf(line_text, 128, "%s = alloca %s", name, ty_s)
# 在入口块终止指令之前插入
block_insert_text_before_terminator(pool, entry_blk, line_text)
# 结果类型是 ty*
result_ty: LLVMType | t.CPtr = LLVMType.Ptr(ty)
result_ty_ptr: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if result_ty_ptr is not None:
string.memset(result_ty_ptr, 0, LLVMType.__sizeof__())
c.DerefAs(result_ty_ptr, result_ty)
return SSAValue(pool, result_ty_ptr, name)
def build_load(builder: IRBuilder | t.CPtr, ty: LLVMType | t.CPtr,
ptr: Value | t.CPtr) -> Value | t.CPtr:
"""%N = load <ty>, <ptr_ty> <ptr>"""
@@ -510,30 +541,30 @@ def build_call(builder: IRBuilder | t.CPtr, callee: t.CChar | t.CPtr,
ret_ty_s: t.CChar | t.CPtr = _type_str(builder, ret_ty)
# 构建参数列表文本 + 变参函数类型签名
args_buf: t.CChar | t.CPtr = pool.alloc(256)
args_buf: t.CChar | t.CPtr = pool.alloc(1024)
if args_buf is None: return None
args_buf[0] = '\0'
func_ty_buf: t.CChar | t.CPtr = pool.alloc(256)
func_ty_buf: t.CChar | t.CPtr = pool.alloc(1024)
if func_ty_buf is None: return None
func_ty_buf[0] = '\0'
cur: Value | t.CPtr = args
first: t.CInt = 1
while cur is not None:
if first == 0:
_append_cstr(args_buf, 256, ", ")
_append_cstr(func_ty_buf, 256, ", ")
_append_cstr(args_buf, 1024, ", ")
_append_cstr(func_ty_buf, 1024, ", ")
arg_ty_s: t.CChar | t.CPtr = _type_str(builder, cur.Ty)
_append_cstr(args_buf, 256, arg_ty_s)
_append_cstr(args_buf, 256, " ")
_append_cstr(args_buf, 1024, arg_ty_s)
_append_cstr(args_buf, 1024, " ")
if cur.Name is not None:
_append_cstr(args_buf, 256, cur.Name)
_append_cstr(func_ty_buf, 256, arg_ty_s)
_append_cstr(args_buf, 1024, cur.Name)
_append_cstr(func_ty_buf, 1024, arg_ty_s)
cur = cur.Next
first = 0
if is_variadic == 1:
if first == 0:
_append_cstr(func_ty_buf, 256, ", ")
_append_cstr(func_ty_buf, 256, "...")
_append_cstr(func_ty_buf, 1024, ", ")
_append_cstr(func_ty_buf, 1024, "...")
# 构造带引号的 callee 名字SHA1 前缀名含 '.' 或以数字开头需要加引号)
callee_buf: t.CChar | t.CPtr = pool.alloc(128)
@@ -546,18 +577,18 @@ def build_call(builder: IRBuilder | t.CPtr, callee: t.CChar | t.CPtr,
else:
_append_cstr(callee_buf, 128, callee)
line: t.CChar | t.CPtr = pool.alloc(512)
line: t.CChar | t.CPtr = pool.alloc(2048)
if line is None: return None
if is_variadic == 1:
if is_void == 1:
viperlib.snprintf(line, 512, "call %s (%s) @%s(%s)", ret_ty_s, func_ty_buf, callee_buf, args_buf)
viperlib.snprintf(line, 2048, "call %s (%s) @%s(%s)", ret_ty_s, func_ty_buf, callee_buf, args_buf)
else:
viperlib.snprintf(line, 512, "%s = call %s (%s) @%s(%s)", name, ret_ty_s, func_ty_buf, callee_buf, args_buf)
viperlib.snprintf(line, 2048, "%s = call %s (%s) @%s(%s)", name, ret_ty_s, func_ty_buf, callee_buf, args_buf)
else:
if is_void == 1:
viperlib.snprintf(line, 512, "call %s @%s(%s)", ret_ty_s, callee_buf, args_buf)
viperlib.snprintf(line, 2048, "call %s @%s(%s)", ret_ty_s, callee_buf, args_buf)
else:
viperlib.snprintf(line, 512, "%s = call %s @%s(%s)", name, ret_ty_s, callee_buf, args_buf)
viperlib.snprintf(line, 2048, "%s = call %s @%s(%s)", name, ret_ty_s, callee_buf, args_buf)
_emit(builder, line)
if is_void == 1:
@@ -594,28 +625,28 @@ def build_call_indirect(builder: IRBuilder | t.CPtr, callee_val: Value | t.CPtr,
ret_ty_s: t.CChar | t.CPtr = _type_str(builder, ret_ty)
# 构建参数列表文本
args_buf: t.CChar | t.CPtr = pool.alloc(256)
args_buf: t.CChar | t.CPtr = pool.alloc(1024)
if args_buf is None: return None
args_buf[0] = '\0'
cur: Value | t.CPtr = args
first: t.CInt = 1
while cur is not None:
if first == 0:
_append_cstr(args_buf, 256, ", ")
_append_cstr(args_buf, 1024, ", ")
arg_ty_s: t.CChar | t.CPtr = _type_str(builder, cur.Ty)
_append_cstr(args_buf, 256, arg_ty_s)
_append_cstr(args_buf, 256, " ")
_append_cstr(args_buf, 1024, arg_ty_s)
_append_cstr(args_buf, 1024, " ")
if cur.Name is not None:
_append_cstr(args_buf, 256, cur.Name)
_append_cstr(args_buf, 1024, cur.Name)
cur = cur.Next
first = 0
line: t.CChar | t.CPtr = pool.alloc(512)
line: t.CChar | t.CPtr = pool.alloc(2048)
if line is None: return None
if is_void == 1:
viperlib.snprintf(line, 512, "call %s %s(%s)", ret_ty_s, callee_val.Name, args_buf)
viperlib.snprintf(line, 2048, "call %s %s(%s)", ret_ty_s, callee_val.Name, args_buf)
else:
viperlib.snprintf(line, 512, "%s = call %s %s(%s)", name, ret_ty_s, callee_val.Name, args_buf)
viperlib.snprintf(line, 2048, "%s = call %s %s(%s)", name, ret_ty_s, callee_val.Name, args_buf)
_emit(builder, line)
if is_void == 1:
@@ -885,17 +916,27 @@ def build_gep_struct(builder: IRBuilder | t.CPtr, struct_ty: LLVMType | t.CPtr,
struct_ty_s: t.CChar | t.CPtr = _type_str(builder, struct_ty)
ptr_ty_s: t.CChar | t.CPtr = _type_str(builder, ptr.Ty)
line: t.CChar | t.CPtr = pool.alloc(2048)
if line is None: return None
if line is None:
stdio.printf("[BGS] line alloc None\n")
stdio.fflush(0)
return None
viperlib.snprintf(line, 2048, "%s = getelementptr %s, %s %s, i32 0, i32 %d",
name, struct_ty_s, ptr_ty_s, ptr.Name, field_idx)
_emit(builder, line)
# GEP 结果类型是 field_ty*
result_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if result_ty is not None:
if result_ty is None:
stdio.printf("[BGS] result_ty alloc None\n")
stdio.fflush(0)
else:
string.memset(result_ty, 0, LLVMType.__sizeof__())
c.DerefAs(result_ty, LLVMType.Ptr(field_ty))
return SSAValue(pool, result_ty, name)
rv: Value | t.CPtr = SSAValue(pool, result_ty, name)
if rv is None:
stdio.printf("[BGS] SSAValue None\n")
stdio.fflush(0)
return rv
# ============================================================
@@ -938,34 +979,35 @@ def build_phi(builder: IRBuilder | t.CPtr, ty: LLVMType | t.CPtr,
ty_s: t.CChar | t.CPtr = _type_str(builder, ty)
# 构建入边列表文本: [val, %blk], [val, %blk], ...
parts: t.CChar | t.CPtr = pool.alloc(512)
# 入边可能很多(如 30+ 个 or 链的 bool.merge需要大缓冲区
parts: t.CChar | t.CPtr = pool.alloc(4096)
if parts is None: return None
parts[0] = '\0'
cur: PhiIncoming | t.CPtr = incoming_head
first: t.CInt = 1
while cur is not None:
if first == 0:
_append_cstr(parts, 512, ", ")
_append_cstr(parts, 512, "[")
_append_cstr(parts, 4096, ", ")
_append_cstr(parts, 4096, "[")
# 使用中间变量避免链式结构体成员访问被编译器丢弃
inc_val: Value | t.CPtr = cur.Val
if inc_val is not None:
inc_val_name: t.CChar | t.CPtr = inc_val.Name
if inc_val_name is not None:
_append_cstr(parts, 512, inc_val_name)
_append_cstr(parts, 512, ", %")
_append_cstr(parts, 4096, inc_val_name)
_append_cstr(parts, 4096, ", %")
inc_blk: BasicBlock | t.CPtr = cur.Block
if inc_blk is not None:
inc_blk_name: t.CChar | t.CPtr = inc_blk.Name
if inc_blk_name is not None:
_append_cstr(parts, 512, inc_blk_name)
_append_cstr(parts, 512, "]")
_append_cstr(parts, 4096, inc_blk_name)
_append_cstr(parts, 4096, "]")
cur = cur.Next
first = 0
line: t.CChar | t.CPtr = pool.alloc(640)
line: t.CChar | t.CPtr = pool.alloc(8192)
if line is None: return None
viperlib.snprintf(line, 640, "%s = phi %s %s", name, ty_s, parts)
viperlib.snprintf(line, 8192, "%s = phi %s %s", name, ty_s, parts)
_emit(builder, line)
return SSAValue(pool, ty, name)