diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-01-23 18:54:13 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-01-25 22:47:12 -0700 |
commit | a8c2f255d43b81821b1237238e742eab82b4ad44 (patch) | |
tree | d9c94d458792501a851564d4af4a81a76fdf944f /build-aux | |
parent | fbc408b36495a60aaf87f5e368a11f57f246d023 (diff) |
stack.c.gen: Allow missing indirect calls
Diffstat (limited to 'build-aux')
-rwxr-xr-x | build-aux/stack.c.gen | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/build-aux/stack.c.gen b/build-aux/stack.c.gen index 0568af0..41fe9c8 100755 --- a/build-aux/stack.c.gen +++ b/build-aux/stack.c.gen @@ -109,11 +109,14 @@ class Node: nstatic: int ndynamic: int - # edges with .sourcename set to this node - calls: set[str] + # edges with .sourcename set to this node, val is if it's + # OK/expected that the function be missing. + calls: dict[str, bool] -def synthetic_node(name: str, nstatic: int, calls: set[str] = set()) -> Node: +def synthetic_node( + name: str, nstatic: int, calls: typing.Collection[str] = set() +) -> Node: n = Node() n.funcname = name @@ -123,7 +126,7 @@ def synthetic_node(name: str, nstatic: int, calls: set[str] = set()) -> Node: n.nstatic = nstatic n.ndynamic = 0 - n.calls = calls + n.calls = dict((c, False) for c in calls) return n @@ -154,7 +157,7 @@ def analyze( match elem.typ: case "node": node = Node() - node.calls = set() + node.calls = {} skip = False for k, v in elem.attrs.items(): match k: @@ -207,9 +210,10 @@ def analyze( raise ValueError(f"unknown caller: {caller}") if callee == "__indirect_call": for callee in app_indirect_callees(elem): - graph[caller].calls.add(callee) + if callee not in graph[caller].calls: + graph[caller].calls[callee] = True else: - graph[caller].calls.add(callee) + graph[caller].calls[callee] = False case _: raise ValueError(f"unknown elem type {repr(elem.typ)}") @@ -245,13 +249,16 @@ def analyze( return None - def nstatic(orig_funcname: str, chain: list[str] = []) -> int: + def nstatic( + orig_funcname: str, chain: list[str] = [], missing_ok: bool = False + ) -> int: nonlocal dbg funcname = resolve_funcname(orig_funcname) if not funcname: if app_skip_call(chain, orig_funcname): return 0 - missing.add(orig_funcname) + if not missing_ok: + missing.add(orig_funcname) return 0 if app_skip_call(chain, funcname): return 0 @@ -265,7 +272,13 @@ def analyze( if node.usage_kind == "dynamic" or node.ndynamic > 0: dynamic.add(app_location_xform(funcname)) return node.nstatic + max( - [0, *[nstatic(call, chain + [funcname]) for call in node.calls]] + [ + 0, + *[ + nstatic(call, chain + [funcname], missing_ok) + for call, missing_ok in node.calls.items() + ], + ] ) print("/*") |