feat(managed): project call and field-access edges into the application graph (#6260)

project_managed_application_graph dropped the call_edges and
field_accesses that member Evidence already decodes, so the graph was a
containment tree that could not answer who calls a P/Invoke wrapper or
which methods touch a field, while reporting complete-within-inputs.

In-module call/callvirt/newobj/jmp sites now become one calls edge per
caller and target, and field loads, stores and address-takes become one
accesses edge per method and field, each with site and per-opcode counts
and member Evidence links. MemberRef and MethodSpec targets, unknown
targets, ldftn/ldvirtftn loads, recursive self-calls (the graph has no
self-loops), MemberRef fields and sites whose node is absent are counted
by reason in limitations, and the graph is partial with that
omitted_count. Add the provider-neutral accesses relation.

Graph Evidence projected before these counters existed still parses,
with null calls and field_accesses summaries.

Fixes #4056

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-22 00:26:56 -07:00
committed by GitHub
parent 86357bad54
commit c9b4cae9dc
9 changed files with 492 additions and 19 deletions
+26
View File
@@ -428,6 +428,32 @@ Declared import inventory supports a bounded positive claim. Its absence does
not exclude dynamic resolution, generated code, protected code, native helpers,
or server-side behavior.
## Application graph relations
`project_managed_application_graph` turns member Evidence into `contains`
edges for declarations, `imports` edges for P/Invoke declarations, and two
relation kinds read from method bodies:
- `calls` links two `managed-method` nodes when a `call`, `callvirt`, `newobj`
or `jmp` site in the caller targets a MethodDef in the inspected module.
- `accesses` links a `managed-method` node to a `managed-field` node for each
field it loads, stores or takes the address of.
Each edge stands for every site between one source and one target. Its
properties carry `site_count` and per-opcode `opcodes` counts; `accesses`
edges also list `access` as `read`, `write` and/or `address`. Edge evidence
links the member Evidence.
Some sites are counted rather than projected: calls to MemberRefs (members of
other assemblies or of generic type instantiations), generic method
instantiations (`MethodSpec`), unknown targets, `ldftn`/`ldvirtftn` function
pointer loads, recursive self-calls (the graph has no self-loops), MemberRef
fields, and sites whose method or field node is absent, for example under a
type selection. Limitations name each counted class, and graph coverage is
`partial` with `omitted_count` equal to the omitted sites when nothing else is
incomplete. A missing `calls` edge is therefore not evidence that a method is
never called.
## Evidence record shape
Member comparison, application graph projection, and managed/native verification