DEV Community

Nnamdi Okpala
Nnamdi Okpala

Posted on

Calling Conventions as Structural Contracts

Calling Conventions as Structural Contracts

At the machine level, computation is not only about values. It is also about where values are placed, in what order they are placed, and how they are recovered.

A calling convention is therefore more than a rule for calling a function. It is a contract describing how two pieces of code agree on the shape of an interaction.

Consider a stack.

A stack is a last-in, first-out (LIFO) data structure. Values are pushed onto the top of the stack, and the most recently pushed value is the first value popped from it.

Conceptually:

push A
push B
push C

Stack:

TOP
 C
 B
 A
Enter fullscreen mode Exit fullscreen mode

Popping produces:

C → B → A
Enter fullscreen mode Exit fullscreen mode

This ordering matters when a calling convention uses the stack for function arguments.

For example, consider:

f(A, B, C);
Enter fullscreen mode Exit fullscreen mode

Under a traditional 32-bit x86 convention such as cdecl, arguments are commonly pushed from right to left:

push C
push B
push A
call f
Enter fullscreen mode Exit fullscreen mode

The call instruction also places the return address on the stack. The called function then interprets the resulting stack layout according to the agreed calling convention.

The important principle is not that arguments must always be reversed. That behaviour is specific to particular ABIs and architectures. The deeper principle is:

The representation used to transfer information must agree with the structure used to retrieve it.

Modern architectures demonstrate this clearly. On x86-64, many function arguments are passed through registers rather than being pushed individually onto the stack. The calling convention still exists, but its structural rules are different.

Different Structures Imply Different Access Rules

A queue has a different structure from a stack.

A queue is first-in, first-out (FIFO):

enqueue A
enqueue B
enqueue C

FRONT → A → B → C ← REAR
Enter fullscreen mode Exit fullscreen mode

Dequeueing produces:

A → B → C
Enter fullscreen mode Exit fullscreen mode

Trying to treat a queue according to stack semantics would change the meaning of the data.

A linked list introduces another structure:

A → B → C → NULL
Enter fullscreen mode Exit fullscreen mode

Here, traversal depends on pointers linking one element to the next.

A tree introduces branching:

        A
       / \
      B   C
     / \
    D   E
Enter fullscreen mode Exit fullscreen mode

Traversal can now take several forms—pre-order, in-order, post-order, breadth-first, and so on.

A priority queue adds another rule: elements are retrieved according to priority rather than simply insertion order. It is often implemented using a binary heap.

For a min-heap:

        1
       / \
      3   4
     / \
    7   9
Enter fullscreen mode Exit fullscreen mode

the smallest element has the highest retrieval priority.

For a max-heap, the ordering is reversed and the largest element occupies the root.

These examples demonstrate that the shape of the structure affects the legal operations performed on it.

The Pointer as a Cursor Through Structure

At the machine level, a pointer can be understood as a cursor identifying a location in memory.

The pointer itself does not know whether the memory represents:

  • a stack,
  • a queue,
  • a linked list,
  • a tree,
  • an array,
  • a heap,
  • a function frame,
  • or some higher-level object.

That interpretation is supplied by the program.

This distinction becomes especially important when C communicates with assembly.

C may express:

result = function(a, b, c);
Enter fullscreen mode Exit fullscreen mode

but the assembly implementation must know exactly where a, b, and c will appear according to the platform ABI.

The assembly routine cannot merely know the values. It must know their layout.

Therefore an assembly interface must define at least:

argument locations
argument ordering
register ownership
stack alignment
return-value location
return-address handling
preserved registers
temporary registers
Enter fullscreen mode Exit fullscreen mode

These rules form the boundary between two computational environments.

Shape Is Part of Meaning

This leads to a useful systems principle:

Data has both value and structure.

The sequence:

A B C
Enter fullscreen mode Exit fullscreen mode

does not mean the same thing under every organization.

As a stack:

C
B
A
Enter fullscreen mode Exit fullscreen mode

determines the next removal as C.

As a queue:

A → B → C
Enter fullscreen mode Exit fullscreen mode

determines the next removal as A.

As a tree, the same three values could instead express a parent-child relationship.

Therefore, when implementing MMUKO components in assembly and exposing them to C, the system should not treat calling conventions as arbitrary plumbing. They should be documented as structural contracts.

The caller constructs a machine state.

The callee interprets that machine state.

Correct execution occurs when both sides agree on the structure.

MMUKO Interpretation

For MMUKO, this principle can extend beyond ordinary function calls.

The system can explicitly describe computational structures in terms of:

shape
orientation
entry point
exit point
ordering
direction of traversal
ownership
transition rules
Enter fullscreen mode Exit fullscreen mode

A stack, queue, ring, tree, or cubit structure can then be treated as a particular computational topology.

This does not mean that a calling convention is literally equivalent to a stack, queue, or heap. Rather:

A calling convention defines how a computational topology is crossed at an interface boundary.

That gives MMUKO a precise foundation for connecting its C and assembly components without making assumptions about the underlying structure.

At the lowest level, the question is not merely:

“What value did we pass?”

It is also:

“What structure did we place that value into, where is the cursor now, and by what rule will the next component retrieve it?”

Top comments (0)