Commit 6ff0eee7 authored by Stefan Behnel's avatar Stefan Behnel

Split up the module init function into separate C functions per setup step as...

Split up the module init function into separate C functions per setup step as it can get fairly lengthy for complex modules, e.g. with many extension types.
This hopefully reduces the function complexity that the C compiler must handle.
parent e0c4e4d2
......@@ -7,10 +7,11 @@ from __future__ import absolute_import
import cython
cython.declare(Naming=object, Options=object, PyrexTypes=object, TypeSlots=object,
error=object, warning=object, py_object_type=object, UtilityCode=object,
EncodedString=object)
EncodedString=object, re=object)
import json
import os
import re
import operator
from .PyrexTypes import CPtrType
from . import Future
......@@ -2261,6 +2262,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.exit_cfunc_scope() # done with labels
def generate_module_init_func(self, imported_modules, env, code):
subfunction = self.mod_init_subfunction(self.scope, code)
code.enter_cfunc_scope(self.scope)
code.putln("")
code.putln(UtilityCode.load_as_string("PyModInitFuncType", "ModuleSetupCode.c")[0])
......@@ -2381,30 +2384,32 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("/*--- Constants init code ---*/")
code.put_error_if_neg(self.pos, "__Pyx_InitCachedConstants()")
code.putln("/*--- Global init code ---*/")
self.generate_global_init_code(env, code)
code.putln("/*--- Global type/function init code ---*/")
with subfunction("Global init code") as inner_code:
self.generate_global_init_code(env, inner_code)
code.putln("/*--- Variable export code ---*/")
self.generate_c_variable_export_code(env, code)
with subfunction("Variable export code") as inner_code:
self.generate_c_variable_export_code(env, inner_code)
code.putln("/*--- Function export code ---*/")
self.generate_c_function_export_code(env, code)
with subfunction("Function export code") as inner_code:
self.generate_c_function_export_code(env, inner_code)
code.putln("/*--- Type init code ---*/")
self.generate_type_init_code(env, code)
with subfunction("Type init code") as inner_code:
self.generate_type_init_code(env, inner_code)
code.putln("/*--- Type import code ---*/")
with subfunction("Type import code") as inner_code:
for module in imported_modules:
self.generate_type_import_code_for_module(module, env, code)
self.generate_type_import_code_for_module(module, env, inner_code)
code.putln("/*--- Variable import code ---*/")
with subfunction("Variable import code") as inner_code:
for module in imported_modules:
self.generate_c_variable_import_code_for_module(module, env, code)
self.generate_c_variable_import_code_for_module(module, env, inner_code)
code.putln("/*--- Function import code ---*/")
with subfunction("Function import code") as inner_code:
for module in imported_modules:
self.specialize_fused_types(module)
self.generate_c_function_import_code_for_module(module, env, code)
self.generate_c_function_import_code_for_module(module, env, inner_code)
code.putln("/*--- Execution code ---*/")
code.mark_pos(None)
......@@ -2469,6 +2474,59 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.exit_cfunc_scope()
def mod_init_subfunction(self, scope, orig_code):
prototypes = orig_code.insertion_point()
prototypes.putln("")
function_code = orig_code.insertion_point()
function_code.putln("")
class ModInitSubfunction(object):
def __init__(self, code_type):
cname = '_'.join(code_type.lower().split())
assert re.match("^[a-z0-9_]+$", cname)
self.cfunc_name = "__Pyx_modinit_%s" % cname
self.description = code_type
self.tempdecl_code = None
self.call_code = None
def __enter__(self):
self.call_code = orig_code.insertion_point()
code = function_code
code.enter_cfunc_scope(scope)
prototypes.putln("static int %s(void); /*proto*/" % self.cfunc_name)
code.putln("static int %s(void) {" % self.cfunc_name)
# Leave a grepable marker that makes it easy to find the generator source.
code.putln("/*--- %s ---*/" % self.description)
self.tempdecl_code = code.insertion_point()
return code
def __exit__(self, *args):
code = function_code
code.putln("return 0;")
self.tempdecl_code.put_temp_declarations(code.funcstate)
self.tempdecl_code = None
needs_error_handling = code.label_used(code.error_label)
if needs_error_handling:
code.put_label(code.error_label)
for cname, type in code.funcstate.all_managed_temps():
code.put_xdecref(cname, type)
code.putln("return -1;")
code.putln("}")
code.exit_cfunc_scope()
code.putln("")
if needs_error_handling:
self.call_code.use_label(orig_code.error_label)
self.call_code.putln("if (unlikely(%s() != 0)) goto %s;" % (
self.cfunc_name, orig_code.error_label))
else:
self.call_code.putln("(void)%s();" % self.cfunc_name)
self.call_code = None
return ModInitSubfunction
def generate_module_import_setup(self, env, code):
module_path = env.directives['set_initial_path']
if module_path == 'SOURCEFILE':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment