py/objmodule: Add a table of built-in modules with delegation.

This replaces the previous QSTR_null entry in the globals dict which could
leak out to Python (e.g. via iteration of mod.__dict__) and could lead to
crashes.

It results in smaller code size at the expense of turning a lookup into a
loop, but the list it is looping over likely only contains one or two
elements.

To allow a module to register its custom attr function it can use the new
`MP_REGISTER_MODULE_DELEGATION` macro.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
Jim Mussared
2023-06-05 15:52:57 +10:00
parent eb85f4d4c9
commit 13c817e61c
9 changed files with 67 additions and 36 deletions

View File

@@ -22,11 +22,16 @@ import io
import argparse
pattern = re.compile(
register_pattern = re.compile(
r"\s*(MP_REGISTER_MODULE|MP_REGISTER_EXTENSIBLE_MODULE)\(MP_QSTR_(.*?),\s*(.*?)\);",
flags=re.DOTALL,
)
delegation_pattern = re.compile(
r"\s*(?:MP_REGISTER_MODULE_DELEGATION)\((.*?),\s*(.*?)\);",
flags=re.DOTALL,
)
def find_module_registrations(filename):
"""Find any MP_REGISTER_MODULE definitions in the provided file.
@@ -37,7 +42,8 @@ def find_module_registrations(filename):
global pattern
with io.open(filename, encoding="utf-8") as c_file_obj:
return set(re.findall(pattern, c_file_obj.read()))
c = c_file_obj.read()
return set(re.findall(register_pattern, c)), set(re.findall(delegation_pattern, c))
def generate_module_table_header(modules):
@@ -50,7 +56,6 @@ def generate_module_table_header(modules):
# Print header file for all external modules.
mod_defs = set()
extensible_mod_defs = set()
print("// Automatically generated by makemoduledefs.py.\n")
for macro_name, module_name, obj_module in modules:
mod_def = "MODULE_DEF_{}".format(module_name.upper())
if macro_name == "MP_REGISTER_MODULE":
@@ -97,13 +102,27 @@ def generate_module_table_header(modules):
print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES")
def generate_module_delegations(delegations):
print("\n#define MICROPY_MODULE_DELEGATIONS \\")
for obj_module, fun_name in delegations:
print(
" {{ MP_ROM_PTR(&{obj_module}), {fun_name} }},".format(
obj_module=obj_module, fun_name=fun_name
)
)
print("// MICROPY_MODULE_DELEGATIONS")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("file", nargs=1, help="file with MP_REGISTER_MODULE definitions")
args = parser.parse_args()
modules = find_module_registrations(args.file[0])
print("// Automatically generated by makemoduledefs.py.\n")
modules, delegations = find_module_registrations(args.file[0])
generate_module_table_header(sorted(modules))
generate_module_delegations(sorted(delegations))
if __name__ == "__main__":