修正了一些错误
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user