Named contexts
A context may carry a name: a machine-generated identifier that gives
the context a stable identity other contexts can reference. A name is
what makes a cross-context reference possible — one context declares
a name, and another points back to it by the same name.
Names are opaque strings; the format imposes no structure on them.
Within a single program — one instructions
sequence — each name must be declared by exactly one context; no
two contexts may declare the same name. Other contexts may reference
that name freely — that repetition is how they point back — and every
reference resolves to the single declaring context. Compilers
should also choose names that are meaningful to debugger users.
- Explore
- View source
- Playground
- YAML
- JSON
$schema: "https://json-schema.org/draft/2020-12/schema"
$id: "schema:ethdebug/format/program/context/name"
title: ethdebug/format/program/context/name
description: |
A machine-generated identifier for this context that other
contexts may reference by name.
A `name` gives a context a stable identity that the rest of a
program's debug information can point back to. This is what makes
cross-context references possible. Uses include:
- **Selecting `pick` alternatives.** Several contexts may apply
at a point in execution; a `name` identifies which alternative
is active, so runtime information can select it.
- **Correlating an invocation with its return.** An `invoke`
context *declares* an activation's name; the matching `return`
context — and the instructions belonging to that activation —
*reference* it by the same name. This pairs a call with its
return directly, without relying on the trace being strictly
nested (see the invoke context's activation-reconstruction
guidance).
Names are opaque strings; the format imposes no structure on
them. Within a single program — one **instructions** sequence —
each name **must** be declared by exactly one context; no two
contexts may declare the same name. Other contexts may reference
that name freely, and every reference resolves to the single
declaring context. Compilers **should** also choose names that
are meaningful to debugger users.
type: object
properties:
name:
type: string
required:
- name
examples:
# example: declaring an inlined activation, referenced by its
# matching return and by the instructions of the inlined body
- name: "inline-0"
# example: naming a generic instantiation
- name: "Array<T=bytes32>"
# example: distinguishing a `pick` alternative
- name: "storage-layout-v2"
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "schema:ethdebug/format/program/context/name",
"title": "ethdebug/format/program/context/name",
"description": "A machine-generated identifier for this context that other\ncontexts may reference by name.\n\nA `name` gives a context a stable identity that the rest of a\nprogram's debug information can point back to. This is what makes\ncross-context references possible. Uses include:\n\n- **Selecting `pick` alternatives.** Several contexts may apply\n at a point in execution; a `name` identifies which alternative\n is active, so runtime information can select it.\n- **Correlating an invocation with its return.** An `invoke`\n context *declares* an activation's name; the matching `return`\n context — and the instructions belonging to that activation —\n *reference* it by the same name. This pairs a call with its\n return directly, without relying on the trace being strictly\n nested (see the invoke context's activation-reconstruction\n guidance).\n\nNames are opaque strings; the format imposes no structure on\nthem. Within a single program — one **instructions** sequence —\neach name **must** be declared by exactly one context; no two\ncontexts may declare the same name. Other contexts may reference\nthat name freely, and every reference resolves to the single\ndeclaring context. Compilers **should** also choose names that\nare meaningful to debugger users.\n",
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
],
"examples": [
{
"name": "inline-0"
},
{
"name": "Array<T=bytes32>"
},
{
"name": "storage-layout-v2"
}
]
}
Uses
Selecting pick alternatives
Inside a pick, several contexts may apply
at a given point in execution and runtime information is needed to select
which one is active. A name on each alternative gives the selection
a stable handle for the chosen alternative.
Correlating an invocation with its return
A name lets a function invocation and its return be paired directly.
An invoke context declares
an activation's name; the matching
return context — and the
instructions belonging to that activation's body — reference it by
the same name.
This declaration/reference split follows the format's general reference-by-name idiom (as a pointer template is declared once and referenced elsewhere). It pairs a call with its return without relying on the trace being strictly nested: even when optimization reorders or interleaves code so that a naive "innermost open activation" rule would mispair them, the shared name resolves the pairing unambiguously. When two inlined copies of the same function appear back-to-back, their distinct names keep them distinct activations.
Because a single context object can hold at most one name, two
activation facts that must carry different names at the same
instruction — for example a tail call, where one instruction both
returns from the current activation and invokes the next — are expressed
with a gather whose members each carry
their own name. The naming granularity therefore tracks the structure of
the contexts themselves.
See the invoke context's Reconstructing activations for how a debugger uses these names to rebuild the call stack.