From b4567ffb9a9c1c9acdb6ea38694908555ac4594a Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 12 Aug 2026 01:27:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(llvmlite):=20opaque=E4=B8=8E=E7=A9=BA?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BD=93=E5=8C=BA=E5=88=86(fcount=E5=93=A8?= =?UTF-8?q?=E5=85=B5)=EF=BC=9Bast=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/ast/__init__.vp | 2 +- includes/ast/base.vp | 11 ++++--- includes/ast/exprs.vp | 56 +++++++++++++++++------------------ includes/llvmlite/__module.vp | 24 +++++++++++---- includes/llvmlite/__types.vp | 7 +++-- 5 files changed, 58 insertions(+), 42 deletions(-) diff --git a/includes/ast/__init__.vp b/includes/ast/__init__.vp index 6799553..5f2a60a 100644 --- a/includes/ast/__init__.vp +++ b/includes/ast/__init__.vp @@ -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, diff --git a/includes/ast/base.vp b/includes/ast/base.vp index 440c80b..fb3134c 100644 --- a/includes/ast/base.vp +++ b/includes/ast/base.vp @@ -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/...)""" diff --git a/includes/ast/exprs.vp b/includes/ast/exprs.vp index a9217d6..366fffc 100644 --- a/includes/ast/exprs.vp +++ b/includes/ast/exprs.vp @@ -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 diff --git a/includes/llvmlite/__module.vp b/includes/llvmlite/__module.vp index d64fc6c..2572364 100644 --- a/includes/llvmlite/__module.vp +++ b/includes/llvmlite/__module.vp @@ -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) # 递归扫描结构体字段中的跨模块引用 diff --git a/includes/llvmlite/__types.vp b/includes/llvmlite/__types.vp index 58ab93b..dae4d99 100644 --- a/includes/llvmlite/__types.vp +++ b/includes/llvmlite/__types.vp @@ -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)