Skip to content

Commit 8864511

Browse files
authored
Add function call tracing documentation (#187)
* Add function call tracing documentation Add invoke/return/revert context documentation across concept, reference, and spec pages: - concepts/programs.mdx: new "Function call contexts" section explaining the three context types with a SchemaExample - tracing.mdx: walkthrough of tracing through an internal function call (Adder contract), plus external call and revert examples - Spec pages: added intro prose to function.mdx, return.mdx, revert.mdx * Make function call tracing example interactive Replace the static BUG code block with an interactive TraceExample component that lets readers compile and step through the Adder contract, seeing invoke/return contexts at function boundaries. Static SchemaExample blocks are kept for the narrative walkthrough and for external call/revert examples (which BUG can't demonstrate). * Fix BUG source indentation in tracing examples Add 2-space indentation inside block bodies (storage, create, code, if) to match the canonical style used in .bug example files. * Revert BUG indentation to match prettier formatting Prettier strips indentation inside template literal strings in MDX JSX props. Revert to the unindented style that prettier enforces.
1 parent 17a7b13 commit 8864511

5 files changed

Lines changed: 236 additions & 1 deletion

File tree

packages/web/docs/concepts/programs.mdx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,55 @@ Contexts can be composed using:
157157
This composition enables describing complex scenarios like conditional variable
158158
assignments or function inlining.
159159

160+
## Function call contexts
161+
162+
Programs answer "what function are we in?" through three context types
163+
that track function boundaries during execution:
164+
165+
- **invoke** — marks an instruction that enters a function. Indicates
166+
the invocation kind (internal jump, external message call, or
167+
contract creation) and provides pointers to call arguments, target
168+
address, gas, and value as appropriate.
169+
- **return** — marks an instruction associated with a successful
170+
return from a function. Provides a pointer to the return data.
171+
- **revert** — marks an instruction associated with a failed call.
172+
May include a pointer to revert reason data or a numeric panic
173+
code.
174+
175+
All three extend a common **function identity** schema with optional
176+
fields for the function's name, declaration source range, and type.
177+
This lets compilers provide as much or as little attribution as
178+
available — from a fully identified `transfer` call down to an
179+
anonymous indirect invocation through a function pointer.
180+
181+
<SchemaExample
182+
schema="program/context/function/invoke"
183+
href="/spec/program/context/function/invoke"
184+
title="Internal function call"
185+
>
186+
{`{
187+
"invoke": {
188+
"identifier": "transfer",
189+
"jump": true,
190+
"target": {
191+
"pointer": { "location": "stack", "slot": 0 }
192+
},
193+
"arguments": {
194+
"pointer": {
195+
"group": [
196+
{ "name": "to", "location": "stack", "slot": 2 },
197+
{ "name": "amount", "location": "stack", "slot": 3 }
198+
]
199+
}
200+
}
201+
}
202+
}`}
203+
</SchemaExample>
204+
205+
A debugger uses these contexts to reconstruct call stacks, show
206+
function names in stepping UI, and display argument/return values
207+
alongside source code.
208+
160209
## What tracing enables
161210

162211
By following contexts through execution, debuggers can provide:

packages/web/docs/core-schemas/programs/tracing.mdx

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,178 @@ b = b + 1;
121121
}`}
122122
/>
123123

124+
## Tracing through a function call
125+
126+
The examples above trace simple straight-line code. Real programs
127+
make function calls. **invoke** and **return** contexts let a
128+
debugger follow execution across function boundaries.
129+
130+
Click **"Try it"** on the example below, then step through the
131+
trace. Watch for **invoke** contexts on the JUMP into `add` and
132+
**return** contexts on the JUMP back to the caller:
133+
134+
<TraceExample
135+
title="Function call and return"
136+
description="Calls an internal add function and stores the result"
137+
source={`name Adder;
138+
139+
define {
140+
function add(a: uint256, b: uint256) -> uint256 {
141+
return a + b;
142+
};
143+
}
144+
145+
storage {
146+
[0] result: uint256;
147+
}
148+
149+
create {
150+
result = 0;
151+
}
152+
153+
code {
154+
result = add(3, 4);
155+
}`}
156+
/>
157+
158+
As you step through, three phases are visible:
159+
160+
### Before the call — setting up arguments
161+
162+
At the call site, the compiler pushes arguments onto the stack and
163+
prepares the jump. The JUMP instruction carries an **invoke**
164+
context identifying the function, its target, and the argument
165+
locations:
166+
167+
<SchemaExample
168+
schema="program/context/function/invoke"
169+
href="/spec/program/context/function/invoke"
170+
title="Invoke context on the JUMP"
171+
>
172+
{`{
173+
"invoke": {
174+
"identifier": "add",
175+
"jump": true,
176+
"target": {
177+
"pointer": { "location": "stack", "slot": 0 }
178+
},
179+
"arguments": {
180+
"pointer": {
181+
"group": [
182+
{ "name": "a", "location": "stack", "slot": 2 },
183+
{ "name": "b", "location": "stack", "slot": 3 }
184+
]
185+
}
186+
}
187+
}
188+
}`}
189+
</SchemaExample>
190+
191+
The debugger now knows it's entering `add` with arguments at stack
192+
slots 2 and 3. A trace viewer can show `add(3, 4)` in the call
193+
stack.
194+
195+
### Inside the function — normal tracing
196+
197+
Inside `add`, instructions carry their own `code` and `variables`
198+
contexts as usual. The debugger shows the source range within the
199+
function body, and parameters `a` and `b` appear as in-scope
200+
variables.
201+
202+
### Returning — the result
203+
204+
When `add` finishes, the JUMP back to the caller carries a
205+
**return** context with a pointer to the result:
206+
207+
<SchemaExample
208+
schema="program/context/function/return"
209+
href="/spec/program/context/function/return"
210+
title="Return context on the JUMP back"
211+
>
212+
{`{
213+
"return": {
214+
"identifier": "add",
215+
"data": {
216+
"pointer": { "location": "stack", "slot": 0 }
217+
}
218+
}
219+
}`}
220+
</SchemaExample>
221+
222+
The debugger pops `add` from the call stack and can display the
223+
return value (7).
224+
225+
### External calls and reverts
226+
227+
The same pattern applies to external message calls, but with
228+
additional fields. An external CALL instruction carries gas, value,
229+
and input data pointers:
230+
231+
<SchemaExample
232+
schema="program/context/function/invoke"
233+
href="/spec/program/context/function/invoke"
234+
title="External call (CALL)"
235+
>
236+
{`{
237+
"invoke": {
238+
"identifier": "balanceOf",
239+
"message": true,
240+
"target": {
241+
"pointer": { "location": "stack", "slot": 1 }
242+
},
243+
"gas": {
244+
"pointer": { "location": "stack", "slot": 0 }
245+
},
246+
"input": {
247+
"pointer": {
248+
"group": [
249+
{ "name": "selector", "location": "memory",
250+
"offset": "0x80", "length": 4 },
251+
{ "name": "arguments", "location": "memory",
252+
"offset": "0x84", "length": "0x20" }
253+
]
254+
}
255+
}
256+
}
257+
}`}
258+
</SchemaExample>
259+
260+
If the call reverts, a **revert** context captures the reason:
261+
262+
<SchemaExample
263+
schema="program/context/function/revert"
264+
href="/spec/program/context/function/revert"
265+
title="Revert with reason"
266+
>
267+
{`{
268+
"revert": {
269+
"identifier": "transfer",
270+
"reason": {
271+
"pointer": {
272+
"location": "memory",
273+
"offset": "0x80",
274+
"length": "0x64"
275+
}
276+
}
277+
}
278+
}`}
279+
</SchemaExample>
280+
281+
For built-in assertion failures, the compiler can provide a panic
282+
code instead of (or alongside) a reason pointer:
283+
284+
<SchemaExample
285+
schema="program/context/function/revert"
286+
href="/spec/program/context/function/revert"
287+
title="Arithmetic overflow panic"
288+
>
289+
{`{
290+
"revert": {
291+
"panic": 17
292+
}
293+
}`}
294+
</SchemaExample>
295+
124296
## Trace data structure
125297

126298
A trace step captures the EVM state at a single point:

packages/web/spec/program/context/function/function.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import SchemaViewer from "@site/src/components/SchemaViewer";
77
# Function identity
88

99
Function contexts (invoke, return, revert) share a common set of
10-
identity fields for the function being called.
10+
identity fields for the function being called. All fields are
11+
optional, allowing compilers to provide as much or as little
12+
detail as available — from a fully named function with source
13+
location and type, down to an empty object for an anonymous
14+
indirect call.
1115

1216
<SchemaViewer
1317
schema={{ id: "schema:ethdebug/format/program/context/function" }}

packages/web/spec/program/context/function/return.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import SchemaViewer from "@site/src/components/SchemaViewer";
66

77
# Return contexts
88

9+
A return context marks an instruction associated with a successful
10+
function return. It extends the function identity schema with a
11+
pointer to the return data and, for external calls, the success
12+
status.
13+
914
<SchemaViewer
1015
schema={{ id: "schema:ethdebug/format/program/context/function/return" }}
1116
/>

packages/web/spec/program/context/function/revert.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import SchemaViewer from "@site/src/components/SchemaViewer";
66

77
# Revert contexts
88

9+
A revert context marks an instruction associated with a function
10+
revert. It extends the function identity schema with an optional
11+
pointer to revert reason data and/or a numeric panic code for
12+
built-in assertion failures.
13+
914
<SchemaViewer
1015
schema={{ id: "schema:ethdebug/format/program/context/function/revert" }}
1116
/>

0 commit comments

Comments
 (0)