fix(llvmlite): opaque与空结构体区分(fcount哨兵);ast表达式节点调整

This commit is contained in:
TermiNexus committed 2026-08-12 01:27:24 +08:00
1 parent 99bf970452
commit b4567ffb9a
5 files changed
+58 -42

No files matched your search

+1 -1
View File
@@ -9,7 +9,7 @@ from .tokens import (
)
# Common Section: Base Classes, Enums, Constants, Helper Functions, Dump
from .base import (
AST, Stmt, Expr, ASTKind, ASTCtx, OpKind, ASTFlag,
AST, Stmt, ExprNode, ASTKind, ASTCtx, OpKind, ASTFlag,
# Constants
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR,
FLAG_IS_ASYNC, FLAG_SIMPLE, FLAG_HAS_STAR,
+7 -4
View File
@@ -472,14 +472,17 @@ class Stmt(AST):
# ============================================================
# Expr - Expression Base Class
# ExprNode - Expression Base Class
#
# 所有表达式节点(Name/Constant/Call/BinOp/...)继承 Expr。
# isinstance(node, ast.Expr) 可在运行时区分"表达式"与"语句"。
# 所有表达式节点(Name/Constant/Call/BinOp/...)继承 ExprNode。
# isinstance(node, ast.ExprNode) 可在运行时区分"表达式"与"语句"。
#
# 命名说明:不能叫 Expr——ASTKind.Expr(base.vp L23)与 stmts.vp 的
# Expr 类已是"表达式语句"(Expression Statement)的既有语义。
# ============================================================
@t.CVTable
class Expr(AST):
class ExprNode(AST):
"""表达式节点基类(Name/Constant/Call/BinOp/...)"""
+28 -28
View File
@@ -3,7 +3,7 @@ from stdint import *
import memhub
import string
from .base import (
AST, Expr, ASTKind, ASTCtx, OpKind,
AST, ExprNode, ASTKind, ASTCtx, OpKind,
_init_ast, _copy_str, _set_parent_list,
_emit, _emit_str, _emit_int, _dump_list, _dump_op_list, _op_name,
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR
@@ -14,7 +14,7 @@ from .base import (
# Name node
# ============================================================
class Name(Expr):
class Name(ExprNode):
"""Name(id: str, ctx: ASTCtx)"""
id: str
ctx: t.CInt
@@ -57,7 +57,7 @@ class Name(Expr):
# Constant nodes (subtype marked by const_kind)
# ============================================================
class Constant(Expr):
class Constant(ExprNode):
"""Constant(int_val/float_val/str_val, const_kind)"""
int_val: t.CInt64T
float_val: t.CDouble
@@ -126,7 +126,7 @@ class Constant(Expr):
# BinOp Node
# ============================================================
class BinOp(Expr):
class BinOp(ExprNode):
"""BinOp(left: AST, op: OpKind, right: AST)"""
left: AST | t.CPtr
op: t.CInt
@@ -174,7 +174,7 @@ class BinOp(Expr):
# UnaryOp Node
# ============================================================
class UnaryOp(Expr):
class UnaryOp(ExprNode):
"""UnaryOp(op: OpKind, operand: AST)"""
op: t.CInt
operand: AST | t.CPtr
@@ -215,7 +215,7 @@ class UnaryOp(Expr):
# Compare Node
# ============================================================
class Compare(Expr):
class Compare(ExprNode):
"""Compare(left: AST, ops: list[CInt], comparators: list[AST | CPtr])"""
left: AST | t.CPtr
ops: t.CPtr
@@ -265,7 +265,7 @@ class Compare(Expr):
# Call Node
# ============================================================
class Call(Expr):
class Call(ExprNode):
"""Call(func: AST, args: list[AST | CPtr], keywords: list[AST | CPtr])"""
func: AST | t.CPtr
args: list[AST | t.CPtr] | t.CPtr
@@ -314,7 +314,7 @@ class Call(Expr):
# BoolOp Node
# ============================================================
class BoolOp(Expr):
class BoolOp(ExprNode):
"""BoolOp(op: CInt, values: list[AST | CPtr])"""
op: t.CInt
values: list[AST | t.CPtr] | t.CPtr
@@ -355,7 +355,7 @@ class BoolOp(Expr):
# Lambda Node
# ============================================================
class Lambda(Expr):
class Lambda(ExprNode):
"""Lambda(args: AST, body: AST)"""
args: AST | t.CPtr
body: AST | t.CPtr
@@ -399,7 +399,7 @@ class Lambda(Expr):
# IfExp Node
# ============================================================
class IfExp(Expr):
class IfExp(ExprNode):
"""IfExp(test: AST, body: AST, orelse: AST)"""
test: AST | t.CPtr
body: AST | t.CPtr
@@ -452,7 +452,7 @@ class IfExp(Expr):
# Dict Node
# ============================================================
class Dict(Expr):
class Dict(ExprNode):
"""Dict(keys: list[AST | CPtr], values: list[AST | CPtr])"""
keys: list[AST | t.CPtr] | t.CPtr
values: list[AST | t.CPtr] | t.CPtr
@@ -494,7 +494,7 @@ class Dict(Expr):
# Set Node
# ============================================================
class Set(Expr):
class Set(ExprNode):
"""Set(elts: list[AST | CPtr])"""
elts: list[AST | t.CPtr] | t.CPtr
@@ -529,7 +529,7 @@ class Set(Expr):
# ListComp Node
# ============================================================
class ListComp(Expr):
class ListComp(ExprNode):
"""ListComp(elt: AST, generators: list[AST | CPtr])"""
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
@@ -573,7 +573,7 @@ class ListComp(Expr):
# SetComp Node
# ============================================================
class SetComp(Expr):
class SetComp(ExprNode):
"""SetComp(elt: AST, generators: list[AST | CPtr])"""
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
@@ -617,7 +617,7 @@ class SetComp(Expr):
# DictComp Node
# ============================================================
class DictComp(Expr):
class DictComp(ExprNode):
"""DictComp(key: AST, value: AST, generators: list[AST | CPtr])"""
key: AST | t.CPtr
value: AST | t.CPtr
@@ -668,7 +668,7 @@ class DictComp(Expr):
# GeneratorExp Node
# ============================================================
class GeneratorExp(Expr):
class GeneratorExp(ExprNode):
"""GeneratorExp(elt: AST, generators: list[AST | CPtr])"""
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
@@ -712,7 +712,7 @@ class GeneratorExp(Expr):
# Await Node
# ============================================================
class Await(Expr):
class Await(ExprNode):
"""Await(value: AST)"""
value: AST | t.CPtr
@@ -747,7 +747,7 @@ class Await(Expr):
# Yield Node
# ============================================================
class Yield(Expr):
class Yield(ExprNode):
"""Yield(value: AST)"""
value: AST | t.CPtr
@@ -782,7 +782,7 @@ class Yield(Expr):
# YieldFrom Node
# ============================================================
class YieldFrom(Expr):
class YieldFrom(ExprNode):
"""YieldFrom(value: AST)"""
value: AST | t.CPtr
@@ -817,7 +817,7 @@ class YieldFrom(Expr):
# FormattedValue Node
# ============================================================
class FormattedValue(Expr):
class FormattedValue(ExprNode):
"""FormattedValue(value: AST, conversion: CInt, format_spec: AST)"""
value: AST | t.CPtr
conversion: t.CInt
@@ -867,7 +867,7 @@ class FormattedValue(Expr):
# JoinedStr Node
# ============================================================
class JoinedStr(Expr):
class JoinedStr(ExprNode):
"""JoinedStr(values: list[AST | CPtr])"""
values: list[AST | t.CPtr] | t.CPtr
@@ -902,7 +902,7 @@ class JoinedStr(Expr):
# Attribute Node
# ============================================================
class Attribute(Expr):
class Attribute(ExprNode):
"""Attribute(value: AST, attr: str, ctx: CInt)"""
value: AST | t.CPtr
attr: str
@@ -947,7 +947,7 @@ class Attribute(Expr):
# Subscript Node
# ============================================================
class Subscript(Expr):
class Subscript(ExprNode):
"""Subscript(value: AST, slice: AST, ctx: CInt)"""
value: AST | t.CPtr
slice: AST | t.CPtr
@@ -995,7 +995,7 @@ class Subscript(Expr):
# Starred Node
# ============================================================
class Starred(Expr):
class Starred(ExprNode):
"""Starred(value: AST, ctx: CInt)"""
value: AST | t.CPtr
ctx: t.CInt
@@ -1036,7 +1036,7 @@ class Starred(Expr):
# List Node
# ============================================================
class List(Expr):
class List(ExprNode):
"""List(elts: list[AST | CPtr], ctx: CInt)"""
elts: list[AST | t.CPtr] | t.CPtr
ctx: t.CInt
@@ -1075,7 +1075,7 @@ class List(Expr):
# Tuple Node
# ============================================================
class Tuple(Expr):
class Tuple(ExprNode):
"""Tuple(elts: list[AST | CPtr], ctx: CInt)"""
elts: list[AST | t.CPtr] | t.CPtr
ctx: t.CInt
@@ -1114,7 +1114,7 @@ class Tuple(Expr):
# Slice Node
# ============================================================
class Slice(Expr):
class Slice(ExprNode):
"""Slice(lower: AST, upper: AST, step: AST)"""
lower: AST | t.CPtr
upper: AST | t.CPtr
@@ -1167,7 +1167,7 @@ class Slice(Expr):
# NamedExpr Node
# ============================================================
class NamedExpr(Expr):
class NamedExpr(ExprNode):
"""NamedExpr(target: AST, value: AST)"""
target: AST | t.CPtr
value: AST | t.CPtr
+18 -6
View File
@@ -366,21 +366,31 @@ def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
# ============================================================
# _is_opaque_struct - 检查类型是否是 opaque 结构体
#
# opaque 结构体特征: Struct 类型,字段数为 0 且字段列表为 None。
# 通过 Struct(pool, None, 0, name) 创建,IR 输出为 %"name" = type opaque。
# opaque 结构体特征: Struct 类型,fcount == -1(哨兵标记,跨模块前向
# 声明,仅名称无字段定义)。通过 Struct(pool, None, -1, name) 创建,
# IR 输出为 %"name" = type opaque。注意区分空结构体(fcount==0,
# fields==None,无字段类)——它是合法完整定义(= type {},可 alloca)。
# 用于在 module_add_named_type 中区分 opaque 声明和完整定义,
# 确保 opaque 声明插入链表头部(在使用之前声明)。
#
# Returns: 1=是 opaque / 0=否
# ============================================================
def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
"""检查类型是否是 opaque 结构体(无字段的命名结构体)"""
"""检查类型是否是 opaque 结构体
opaque 是跨模块前向声明(仅名称无字段定义),由
_scan_type_for_cross_module_refs 创建,fcount=-1 哨兵标记。
空结构体(fcount==0, fields==None,无字段类)是合法完整定义
(LLVM {} 类型,可 alloca),必须与 opaque 区分——此前混淆导致
空类结构体被输出为 "= type opaque",alloca 报 Cannot allocate
unsized type。
"""
if ty is None:
return 0
match ty:
case LLVMType.Struct(fields, fcount, name):
# opaque: 字段数为 0 且字段列表为 None
if fcount == 0 and fields is None:
# opaque: fcount == -1(哨兵)
if fcount < 0:
return 1
return 0
case _:
@@ -425,7 +435,9 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
# 检查是否已在模块中定义
if _is_type_defined_in_module(mod, sname) == 0:
# 创建 opaque 类型并添加到模块
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, 0, sname)
# fcount=-1 哨兵标记 opaque(区别于空结构体 {},
# 后者 fcount==0 是合法完整定义,可 alloca)
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, -1, sname)
if opaque_ty is not None:
module_add_named_type(mod, pool, opaque_ty)
# 递归扫描结构体字段中的跨模块引用
+4 -3
View File
@@ -580,7 +580,8 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""打印命名结构体类型定义行 %"name" = type { ty1, ty2, ... }
当 fcount==0 且 fields is None 时,输出 opaque 声明: %"name" = type opaque
当 fcount == -1(哨兵)时输出 opaque 声明: %"name" = type opaque。
空结构体(fcount==0, fields==None,无字段类)是完整定义,输出 "= type {}"。
"""
if ty is None or buf is None or size == 0:
return
@@ -589,8 +590,8 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
if name is None:
return
# 使用 snprintf 构建 "%%"name" = type" 前缀,避免 _strappend 截断
# opaque 类型: fcount==0 且 fields is None(跨模块前向声明)
if fcount == 0 and fields is None:
# opaque 类型: fcount == -1(哨兵,跨模块前向声明)
if fcount < 0:
viperlib.snprintf(buf, size, "%%\"%s\" = type opaque", name)
else:
viperlib.snprintf(buf, size, "%%\"%s\" = type ", name)