diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index c34a3b2..35b63a0 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -37,7 +37,7 @@ class AnnAssignHandle(BaseHandle): if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.IntType) and Value.type.pointee.width == 8: if 'llvm.memcpy' not in Gen.functions: memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(32), ir.IntType(1)]) - Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy') + Gen.functions['llvm.memcpy'] = Gen._CreateOrReuseFuncDecl('llvm.memcpy', memcpy_type) if isinstance(DestPtr.type.pointee, ir.IntType) and not isinstance(DestPtr.type.pointee, ir.IntType(8)): DestPtr = Gen.builder.bitcast(DestPtr, ir.PointerType(ir.IntType(8)), name=f"strcpy_dst_cast_{VarName}") if isinstance(Value.type.pointee, ir.IntType) and not isinstance(Value.type.pointee, ir.IntType(8)): diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index e9cdeb6..32bcd76 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -843,7 +843,7 @@ class AssignHandle(BaseHandle): MemcpyFunc: ir.Function | None = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') if not MemcpyFunc: MemcpyType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') + MemcpyFunc = Gen._CreateOrReuseFuncDecl('llvm.memcpy.p0i8.p0i8.i64', MemcpyType) Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) VtableCopyGlobalAddr: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") @@ -1125,7 +1125,7 @@ class AssignHandle(BaseHandle): MemcpyFunc: ir.Function | None = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') if not MemcpyFunc: MemcpyType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') + MemcpyFunc = Gen._CreateOrReuseFuncDecl('llvm.memcpy.p0i8.p0i8.i64', MemcpyType) Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) VtableCopyGlobalAddr: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") diff --git a/lib/core/Handles/HandlesAsyncFunctions.py b/lib/core/Handles/HandlesAsyncFunctions.py index a72560b..2bb8415 100644 --- a/lib/core/Handles/HandlesAsyncFunctions.py +++ b/lib/core/Handles/HandlesAsyncFunctions.py @@ -360,7 +360,7 @@ class AsyncFunctionHandle(BaseHandle): if getattr(fn, 'name', None) == 'malloc': return fn malloc_ty: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) - fn: ir.Function = ir.Function(Gen.module, malloc_ty, name='malloc') + fn: ir.Function = Gen._CreateOrReuseFuncDecl('malloc', malloc_ty) Gen.functions['malloc'] = fn return fn @@ -377,7 +377,7 @@ class AsyncFunctionHandle(BaseHandle): params: list[tuple[str, ir.Type]] = getattr(Gen, '_coro_param_vars', {}).get(name, []) param_tys: list[ir.Type] = [ty for _, ty in params] create_ty: ir.FunctionType = ir.FunctionType(ir.PointerType(frame_ty), param_tys) - create_fn: ir.Function = ir.Function(Gen.module, create_ty, name=Gen._mangle_func_name(f'create_{name}')) + create_fn: ir.Function = Gen._CreateOrReuseFuncDecl(Gen._mangle_func_name(f'create_{name}'), create_ty) self._RegisterCoroFunction(Gen, f'create_{name}', create_fn) create_fn.attributes.add('noredzone') entry: ir.Block = create_fn.append_basic_block('entry') @@ -431,7 +431,7 @@ class AsyncFunctionHandle(BaseHandle): def _EmitResumeFunction(self, name: str, Node: ast.AsyncFunctionDef, frame_ty: ir.IdentifiedStructType, Gen: LlvmCodeGenerator) -> None: resume_ty: ir.FunctionType = ir.FunctionType(ir.IntType(32), [ir.PointerType(frame_ty)]) - resume_fn: ir.Function = ir.Function(Gen.module, resume_ty, name=Gen._mangle_func_name(f'resume_{name}')) + resume_fn: ir.Function = Gen._CreateOrReuseFuncDecl(Gen._mangle_func_name(f'resume_{name}'), resume_ty) self._RegisterCoroFunction(Gen, f'resume_{name}', resume_fn) resume_fn.attributes.add('noredzone') Gen.func = resume_fn @@ -674,7 +674,7 @@ class AsyncFunctionHandle(BaseHandle): fn: ir.Function | None = Gen._get_function(name) if fn is not None: return fn - fn = ir.Function(Gen.module, ir.FunctionType(ret_ty, args or []), name=name) + fn = Gen._CreateOrReuseFuncDecl(name, ir.FunctionType(ret_ty, args or [])) Gen.functions[name] = fn return fn @@ -682,7 +682,7 @@ class AsyncFunctionHandle(BaseHandle): for fn in Gen.module.global_values: if getattr(fn, 'name', None) == 'free': return fn - fn = ir.Function(Gen.module, ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]), name='free') + fn = Gen._CreateOrReuseFuncDecl('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) Gen.functions['free'] = fn return fn diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index cf2a632..10ce8fc 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -1430,7 +1430,7 @@ class BaseHandle: Gen.functions[name] = g_existing return g_existing func_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) - func_decl = _ir.Function(Gen.module, func_type, name=name) + func_decl = Gen._CreateOrReuseFuncDecl(name, func_type) Gen.functions[name] = func_decl else: existing = Gen.functions[name] @@ -1467,7 +1467,7 @@ class BaseHandle: if g_ex_decl is not None: func_decl = g_ex_decl else: - func_decl = _ir.Function(Gen.module, stub_func_type, name=decl_name) + func_decl = Gen._CreateOrReuseFuncDecl(decl_name, stub_func_type) Gen.functions[decl_name] = func_decl if alias and alias != decl_name: if not check_existing or alias not in Gen.functions: diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index 7106996..d58044d 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -164,9 +164,12 @@ class ExprHandle(BaseHandle): if not malloc_fn: try: malloc_fn_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) - malloc_fn = ir.Function(Gen.module, malloc_fn_type, name='malloc') + malloc_fn = Gen._CreateOrReuseFuncDecl('malloc', malloc_fn_type) Gen.functions['malloc'] = malloc_fn - except Exception: # 回退:malloc 函数创建失败时返回 null + except Exception as _e: # 回退:malloc 函数创建失败时返回 null + from lib.core.LLVMCG.FuncGen import FailFastError as _FFE + if isinstance(_e, _FFE): + raise return ir.Constant(ir.IntType(8).as_pointer(), None) alloc_ptr: Any = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 0615343..cac113a 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -730,9 +730,12 @@ class ExprBuiltinHandle(BaseHandle): strlen_func = existing if not strlen_func: try: - strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen') + strlen_func = Gen._CreateOrReuseFuncDecl('strlen', correct_strlen_type) Gen.functions['strlen'] = strlen_func except Exception as _e: + from lib.core.LLVMCG.FuncGen import FailFastError as _FFE + if isinstance(_e, _FFE): + raise if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if strlen_func: @@ -1048,7 +1051,7 @@ class ExprBuiltinHandle(BaseHandle): Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if 'llvm.memcpy' not in Gen.functions: memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy') + Gen.functions['llvm.memcpy'] = Gen._CreateOrReuseFuncDecl('llvm.memcpy', memcpy_type) if len(args) >= 3: dst: ir.Value | None = self.HandleExprLlvm(args[0]) src: ir.Value | None = self.HandleExprLlvm(args[1]) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 1652101..5216603 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -1714,13 +1714,13 @@ class ExprCallHandle(BaseHandle): try: func = Gen.module.declare_intrinsic(func_name, [a.type for a in call_args]) except Exception: - func = ir.Function(Gen.module, func_type, name=func_name) + func = Gen._CreateOrReuseFuncDecl(func_name, func_type) else: existing = Gen.module.globals.get(func_name) if existing: func = existing else: - func = ir.Function(Gen.module, func_type, name=func_name) + func = Gen._CreateOrReuseFuncDecl(func_name, func_type) result = Gen.builder.call(func, call_args, name="llvmir_result") if output_targets: return self._StoreLLVMIROutputs(Gen, result, output_targets) @@ -1984,7 +1984,7 @@ class ExprCallHandle(BaseHandle): Gen.functions[func_name] = g_ex_w32 else: func_type = ir.FunctionType(ret_type, param_types) - func_decl = ir.Function(Gen.module, func_type, name=func_name) + func_decl = Gen._CreateOrReuseFuncDecl(func_name, func_type) func_decl.linkage = 'external' Gen.functions[func_name] = func_decl call_args = [] @@ -4158,9 +4158,12 @@ class ExprCallHandle(BaseHandle): strlen_func = existing if not strlen_func: try: - strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen') + strlen_func = Gen._CreateOrReuseFuncDecl('strlen', correct_strlen_type) Gen.functions['strlen'] = strlen_func except Exception as _e: + from lib.core.LLVMCG.FuncGen import FailFastError as _FFE + if isinstance(_e, _FFE): + raise if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if strlen_func: @@ -4783,7 +4786,7 @@ class ExprCallHandle(BaseHandle): Gen = self.Trans.LlvmGen if 'llvm.memcpy' not in Gen.functions: memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy') + Gen.functions['llvm.memcpy'] = Gen._CreateOrReuseFuncDecl('llvm.memcpy', memcpy_type) if len(args) >= 3: dst = self.HandleExprLlvm(args[0]) src = self.HandleExprLlvm(args[1]) diff --git a/lib/core/Handles/HandlesExprLambda.py b/lib/core/Handles/HandlesExprLambda.py index 7078ad6..cb1e883 100644 --- a/lib/core/Handles/HandlesExprLambda.py +++ b/lib/core/Handles/HandlesExprLambda.py @@ -29,7 +29,7 @@ class ExprLambdaHandle(BaseHandle): for arg in Node.args.args: param_types.append(ir.IntType(32)) fn_type: ir.FunctionType = ir.FunctionType(ret_type, param_types) - fn: ir.Function = ir.Function(Gen.module, fn_type, name=fn_name) + fn: ir.Function = Gen._CreateOrReuseFuncDecl(fn_name, fn_type) Gen.functions[fn_name] = fn entry_block: ir.Block = fn.append_basic_block(name=f"{fn_name}_entry") prev_builder: Any = Gen.builder diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index 79352de..36982b4 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -1319,7 +1319,10 @@ class FunctionHandle(BaseHandle): old_func: Any = Gen.functions.get(MangledName) if old_func is None: try: - return ir.Function(Gen.module, NewFuncType, name=MangledName) + # 走唯一幂等入口:名字可能已存在于 module.globals 但未登记进 Gen.functions + # (别的路径先建过声明)——直接 ir.Function 必抛裸 DuplicatedNameError, + # 入口则同名同类型复用、异类型带两侧签名 fail-fast。 + return Gen._CreateOrReuseFuncDecl(MangledName, NewFuncType) except Exception as _e: # 回退:函数已存在时返回旧函数 from lib.core.LLVMCG.FuncGen import FailFastError as _FFE if isinstance(_e, _FFE): diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 5642d6a..404c13b 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -3718,7 +3718,7 @@ class ImportHandle(BaseHandle): if g_ex_stub is not None: func = g_ex_stub else: - func = ir.Function(Gen.module, func_type, name=func_name) + func = Gen._CreateOrReuseFuncDecl(func_name, func_type) Gen.functions[func_name] = func if '.' in func_name: short_fn = func_name.split('.', 1)[1] diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 63ea982..5178250 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -1603,7 +1603,7 @@ class BaseGenMixin: f'--hotspot-sites: 外部函数 {name} 已存在但签名不一致' f'(期望 {ftype},实际 {existing.ftype})') return existing - return ir.Function(self.module, ftype, name=name) + return self._CreateOrReuseFuncDecl(name, ftype) def _InstallHotspotTruncate( self, @@ -1970,9 +1970,9 @@ class BaseGenMixin: fprintf: ir.Function = self._DeclareExternalFunc( 'fprintf', ir.FunctionType(i32, [i8p, i8p], var_arg=True)) fclose: ir.Function = self._DeclareExternalFunc('fclose', ir.FunctionType(i32, [i8p])) - dump_fn: ir.Function = ir.Function( - self.module, ir.FunctionType(ir.VoidType(), []), - name=self._UniqueGlobalName('__fhs_dump_sites')) + dump_fn: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__fhs_dump_sites'), + ir.FunctionType(ir.VoidType(), [])) dump_fn.linkage = 'internal' b: ir.IRBuilder = ir.IRBuilder(dump_fn.append_basic_block(name='entry')) b.position_at_start(dump_fn.entry_basic_block) @@ -2156,9 +2156,9 @@ class BaseGenMixin: fprintf: ir.Function = self._DeclareExternalFunc( 'fprintf', ir.FunctionType(i32, [i8p, i8p], var_arg=True)) fclose: ir.Function = self._DeclareExternalFunc('fclose', ir.FunctionType(i32, [i8p])) - dump_fn: ir.Function = ir.Function( - self.module, ir.FunctionType(ir.VoidType(), []), - name=self._UniqueGlobalName('__fhs_dump_time')) + dump_fn: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__fhs_dump_time'), + ir.FunctionType(ir.VoidType(), [])) dump_fn.linkage = 'internal' b: ir.IRBuilder = ir.IRBuilder(dump_fn.append_basic_block(name='entry')) b.position_at_start(dump_fn.entry_basic_block) @@ -2310,9 +2310,9 @@ class BaseGenMixin: self.module, i32, name=self._UniqueGlobalName('__fhs_dumped')) guard.linkage = 'internal' guard.initializer = ir.Constant(i32, 0) - dump_all: ir.Function = ir.Function( - self.module, ir.FunctionType(ir.VoidType(), []), - name=self._UniqueGlobalName('__fhs_dump_all')) + dump_all: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__fhs_dump_all'), + ir.FunctionType(ir.VoidType(), [])) dump_all.linkage = 'internal' b: ir.IRBuilder = ir.IRBuilder(dump_all.append_basic_block(name='entry')) do_bb: ir.Block = dump_all.append_basic_block(name='fhs_dump_do') @@ -2327,9 +2327,9 @@ class BaseGenMixin: b.branch(done_bb) b.position_at_end(done_bb) b.ret_void() - ctl_handler: ir.Function = ir.Function( - self.module, ir.FunctionType(i32, [i32]), - name=self._UniqueGlobalName('__fhs_ctl_handler')) + ctl_handler: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__fhs_ctl_handler'), + ir.FunctionType(i32, [i32])) ctl_handler.linkage = 'internal' cb: ir.IRBuilder = ir.IRBuilder(ctl_handler.append_basic_block(name='entry')) cb.call(dump_all, []) @@ -2380,9 +2380,9 @@ class BaseGenMixin: i32: ir.IntType = ir.IntType(32) i8p: ir.PointerType = ir.PointerType(ir.IntType(8)) void_fnptr: ir.PointerType = ir.PointerType(ir.FunctionType(ir.VoidType(), [])) - ctor: ir.Function = ir.Function( - self.module, ir.FunctionType(ir.VoidType(), []), - name=self._UniqueGlobalName('__fhs_sites_ctor')) + ctor: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__fhs_sites_ctor'), + ir.FunctionType(ir.VoidType(), [])) ctor.linkage = 'internal' cb: ir.IRBuilder = ir.IRBuilder(ctor.append_basic_block(name='entry')) self._EmitHotspotDumpRegistration(cb, ctl_handler, dump_all) @@ -2429,9 +2429,9 @@ class BaseGenMixin: i32: ir.IntType = ir.IntType(32) i8p: ir.PointerType = ir.PointerType(ir.IntType(8)) void_fnptr: ir.PointerType = ir.PointerType(ir.FunctionType(ir.VoidType(), [])) - ctor: ir.Function = ir.Function( - self.module, ir.FunctionType(ir.VoidType(), []), - name=self._UniqueGlobalName('__traceback_install_ctor')) + ctor: ir.Function = self._CreateOrReuseFuncDecl( + self._UniqueGlobalName('__traceback_install_ctor'), + ir.FunctionType(ir.VoidType(), [])) ctor.linkage = 'internal' cb: ir.IRBuilder = ir.IRBuilder(ctor.append_basic_block(name='entry')) cb.call(install_fn, []) # Install() 无参;返回值(int)有意忽略 diff --git a/lib/core/LLVMCG/ExprGen.py b/lib/core/LLVMCG/ExprGen.py index d6c80b0..5b36048 100644 --- a/lib/core/LLVMCG/ExprGen.py +++ b/lib/core/LLVMCG/ExprGen.py @@ -237,7 +237,7 @@ class ExprGenMixin: powf: ir.Function | None = self.module.globals.get('llvm.pow.f64') if not powf: fnty: ir.FunctionType = ir.FunctionType(ir.DoubleType(), [ir.DoubleType(), ir.DoubleType()]) - powf = ir.Function(self.module, fnty, name='llvm.pow.f64') + powf = self._CreateOrReuseFuncDecl('llvm.pow.f64', fnty) if lf.type != ir.DoubleType(): lf = self.builder.fpext(lf, ir.DoubleType(), name="ext_f64") if rf.type != ir.DoubleType(): diff --git a/lib/core/LLVMCG/VaArg.py b/lib/core/LLVMCG/VaArg.py index b349639..6dd4a48 100644 --- a/lib/core/LLVMCG/VaArg.py +++ b/lib/core/LLVMCG/VaArg.py @@ -9,7 +9,7 @@ class VaArgMixin: if 'llvm.va_start' in self.functions: return self.functions['llvm.va_start'] ftype: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func: ir.Function = ir.Function(self.module, ftype, name='llvm.va_start') + func: ir.Function = self._CreateOrReuseFuncDecl('llvm.va_start', ftype) self.functions['llvm.va_start'] = func return func @@ -17,7 +17,7 @@ class VaArgMixin: if 'llvm.va_end' in self.functions: return self.functions['llvm.va_end'] ftype: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func: ir.Function = ir.Function(self.module, ftype, name='llvm.va_end') + func: ir.Function = self._CreateOrReuseFuncDecl('llvm.va_end', ftype) self.functions['llvm.va_end'] = func return func