summaryrefslogtreecommitdiff
path: root/build-aux
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-01-23 18:54:13 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-01-25 22:47:12 -0700
commita8c2f255d43b81821b1237238e742eab82b4ad44 (patch)
treed9c94d458792501a851564d4af4a81a76fdf944f /build-aux
parentfbc408b36495a60aaf87f5e368a11f57f246d023 (diff)
stack.c.gen: Allow missing indirect calls
Diffstat (limited to 'build-aux')
-rwxr-xr-xbuild-aux/stack.c.gen33
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("/*")