diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-05-15 01:59:17 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-05-15 14:59:02 -0600 |
commit | e38a2d29292ad3fad64729ef958ff07e3bca02cf (patch) | |
tree | 6b647d225665cd4fb2733a57bdfa5f0e96692995 /build-aux/measurestack | |
parent | 3faaad9fe1f11cfe5699c6720c897bfddc7cf49a (diff) |
Fully banish printf from the firmware
Diffstat (limited to 'build-aux/measurestack')
-rw-r--r-- | build-aux/measurestack/app_main.py | 3 | ||||
-rw-r--r-- | build-aux/measurestack/app_plugins.py | 97 | ||||
-rw-r--r-- | build-aux/measurestack/test_app_plugins.py | 70 |
3 files changed, 1 insertions, 169 deletions
diff --git a/build-aux/measurestack/app_main.py b/build-aux/measurestack/app_main.py index 463447e..4fdfd5c 100644 --- a/build-aux/measurestack/app_main.py +++ b/build-aux/measurestack/app_main.py @@ -48,7 +48,6 @@ def main( plugins += [ app_plugins.CmdPlugin(), libmisc_plugin, - app_plugins.PicoFmtPlugin(arg_pico_platform, []), app_plugins.LibHWPlugin(arg_pico_platform, libmisc_plugin), app_plugins.LibCRPlugin(), app_plugins.LibCRIPCPlugin(), @@ -88,8 +87,6 @@ def main( def misc_filter(name: QName) -> tuple[int, bool]: if name in [ QName("__assert_msg_fail"), - QName("fmt_vfctprintf"), - QName("fmt_vsnprintf"), ]: return 1, False for prefix in ["fmt_print_", "_fmt_print_"]: diff --git a/build-aux/measurestack/app_plugins.py b/build-aux/measurestack/app_plugins.py index fbe137c..6fc81ec 100644 --- a/build-aux/measurestack/app_plugins.py +++ b/build-aux/measurestack/app_plugins.py @@ -19,7 +19,6 @@ __all__ = [ "LibCRIPCPlugin", "Lib9PPlugin", "LibMiscPlugin", - "PicoFmtPlugin", "PicoSDKPlugin", "TinyUSBDevicePlugin", "NewlibPlugin", @@ -369,97 +368,6 @@ class Lib9PPlugin: return {} -class PicoFmtPlugin: - known_fct: dict[BaseName, BaseName] - wont_call_v: typing.Collection[BaseName] - - def __init__( - self, arg_pico_platform: str, wont_call_v: typing.Collection[BaseName] - ) -> None: - self.known_fct = { - # pico_fmt - BaseName("fmt_vsnprintf"): BaseName("_out_buffer"), - } - match arg_pico_platform: - case "rp2040": - self.known_fct.update( - { - # pico_stdio - BaseName("__wrap_vprintf"): BaseName("stdio_buffered_printer"), - BaseName("stdio_vprintf"): BaseName("stdio_buffered_printer"), - } - ) - self.wont_call_v = set([*self.known_fct.values(), *wont_call_v]) - - def is_intrhandler(self, name: QName) -> bool: - return False - - def init_array(self) -> typing.Collection[QName]: - return [] - - def extra_includes(self) -> typing.Collection[BaseName]: - return [] - - def extra_nodes(self) -> typing.Collection[Node]: - return [] - - def indirect_callees( - self, loc: str, line: str - ) -> tuple[typing.Collection[QName], bool] | None: - if "/3rd-party/pico-fmt/" not in loc: - return None - if "/printf.c:" in loc: - m = util.re_call_other.fullmatch(line) - call: str | None = m.group("func") if m else None - if "->fct" in line: - return [x.as_qname() for x in self.known_fct.values()], False - if "specifier_table" in line: - return [ - # pico-fmt - QName("conv_sint"), - QName("conv_uint"), - # QName("conv_double"), - QName("conv_char"), - QName("conv_str"), - QName("conv_ptr"), - QName("conv_pct"), - # libfmt - QName("libfmt_conv_formatter"), - QName("libfmt_conv_quote"), - ], False - return None - - def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: - ret: dict[BaseName, analyze.SkipModel] = { - BaseName("fmt_state_putchar"): analyze.SkipModel( - self.known_fct.keys(), self._skipmodel_fmt_state_putchar - ), - BaseName("_vfctprintf"): analyze.SkipModel( - self.wont_call_v, self._skipmodel__vfctprintf - ), - } - return ret - - def _skipmodel_fmt_state_putchar( - self, chain: typing.Sequence[QName], node: Node, call: QName - ) -> bool: - if call.base() in self.known_fct.values(): - fct: BaseName | None = None - for pcall in reversed(chain): - if pcall.base() in self.known_fct: - fct = self.known_fct[pcall.base()] - return call.base() != fct - return True - return False - - def _skipmodel__vfctprintf( - self, chain: typing.Sequence[QName], node: Node, call: QName - ) -> bool: - if call.base() == BaseName("libfmt_conv_formatter"): - return any(c.base() in self.wont_call_v for c in chain) - return False - - class PicoSDKPlugin: get_init_array: typing.Callable[[], typing.Collection[QName]] app_init_array: typing.Collection[QName] | None @@ -877,10 +785,7 @@ class LibGCCPlugin: return False def init_array(self) -> typing.Collection[QName]: - return [ - QName("libfmt_install_formatter"), - QName("libfmt_install_quote"), - ] + return [] def extra_includes(self) -> typing.Collection[BaseName]: return [] diff --git a/build-aux/measurestack/test_app_plugins.py b/build-aux/measurestack/test_app_plugins.py deleted file mode 100644 index aed0bb4..0000000 --- a/build-aux/measurestack/test_app_plugins.py +++ /dev/null @@ -1,70 +0,0 @@ -# build-aux/measurestack/test_app_plugins.py - Tests for app_plugins.py -# -# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> -# SPDX-License-Identifier: AGPL-3.0-or-later - -# pylint: disable=unused-variable - -import typing - -from . import analyze, app_plugins, testutil, util -from .analyze import QName - - -def test_fct() -> None: - # 1. | a + | b + | - # 2. | fmt_vsnprintf + | vprintf + | - # 3. | fmt_vfctprintf + | fmt_vfctprintf + | - # 4. | fmt_state_putchar + | fmt_state_putchar + | - # 5. | _out_buffer + | stdio_buffered_printer + | - max_call_depth = 5 - exp_a = ["a", "fmt_vsnprintf", "fmt_vfctprintf", "fmt_state_putchar", "_out_buffer"] - exp_b = [ - "b", - "__wrap_vprintf", - "fmt_vfctprintf", - "fmt_state_putchar", - "stdio_buffered_printer", - ] - graph: typing.Sequence[tuple[str, typing.Collection[str]]] = [ - # main.c - ("a", {"fmt_vsnprintf"}), # _out_buffer - ("b", {"vprintf"}), # stdio_buffered_printer - # wrappers - ("fmt_vsnprintf", {"fmt_vfctprintf"}), - ("__wrap_vprintf", {"fmt_vfctprintf"}), - # printf.c - ("fmt_vfctprintf", {"fmt_state_putchar"}), - ("fmt_state_putchar", {"_out_buffer", "stdio_buffered_printer"}), - # fcts - ("_out_buffer", {}), - ("stdio_buffered_printer", {}), - ] - graph_plugin = testutil.GraphProviderPlugin(max_call_depth, graph) - - plugins: list[util.Plugin] = [ - graph_plugin, - app_plugins.LibMiscPlugin(arg_c_fnames=[]), - # fmt_vsnprintf => fct=_out_buffer - # if rp2040: - # __wrap_vprintf => fct=stdio_buffered_printer - # stdio_vprintf => fct=stdio_buffered_printer - app_plugins.PicoFmtPlugin("rp2040", []), - ] - - def test_filter(name: QName) -> tuple[int, bool]: - if str(name.base()) in ["a", "b", "c"]: - return 1, True - return 0, False - - result = analyze.analyze( - ci_fnames=[], - app_func_filters={ - "Main": test_filter, - }, - app=util.PluginApplication(testutil.nop_location_xform, plugins), - cfg_max_call_depth=max_call_depth, - ) - - graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("a")].nstatic, exp_a) - graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("b")].nstatic, exp_b) |