# Locals

There are two usages of locals in zink.

- The parameters of functions are loaded as locals.
- local defined variables in functions.

fn params | local variables | |
---|---|---|

stack | locals[..n] | locals[n..] |

## Function Parameters

Let’s go through the `add-two`

example:

```
(module
(func (param (;0;) i32) (param (;1;) i32) (result i32)
(local.get 0)
(local.get 1)
(i32.add)
)
)
```

`(param (;0;) i32)`

and `(param (;1;) i32)`

will be pushed to the function
locals with index `0`

and index `1`

with their type `i32`

recorded.

`zinkc`

gets the defined local at index `0`

when reaching `(local.get 0)`

,
at index `1`

for `(local.get 1)`

, for example, for `(local.get 0)`

, it will
be translated to:

```
push1 0x00
calldataload
```

for `(local.get 1)`

, that would be

```
push1 0x20
calldataload
```

You may have problem why we `PUSH1 0x20`

while getting local at index `1`

, the
answer is that this offset is calculated by the size of the parameters.

The `CALLDATALOAD`

operator has stack input `i`

and output `data[i]`

while `data[i]`

is a `32-byte`

value starting from the given offset of the calldata, so the minimal
size of our types will be `32-byte`

, therefore, we align all types sizes to `32-byte`

in `zinkc`

.

WARN: We don’t care about the originals offset of the parameters in WASM bcz we will serialize them into our locals and calculate the offsets on our own when need anyway.

type | size | aligned size |
---|---|---|

`i32` | `[u8;4]` | `[u8;32]` |

`i64` | `[u8;8]` | `[u8;32]` |

It is a waste of resources but sadly this is also how EVM works ))

## Local Variables

The locals variables will take the stack items right after the function parameters, for example:

```
(func (result i32)
(local i32)
i32.const 42
local.set 0
local.get 0)
```

In the program above, we set and get `42`

to local variable `0`

and returns it.

While compiling this function, `zinkc`

will push local variable `0`

on the stack
with an initializing value `0`

first, getting with `dup`

and setting with `swap`

and `drop`

.

```
PUSH1 0x00 // initializing value 0 for local 0
//
//
PUSH1 0x28 // push value 42 on stack, the current stack is [0, 42]
//
//
SWAP1 // swap the value on the top of the stack to local 0 and
DROP // drop the previous value of it for cleaning stack, `swapn`
// is calculated by `zinkc`. current stack: [42]
//
//
DUP1 // dup the value of local 0 and push it on the top of the
// stack, `dupn` is calculated by `zinkc`.
//
//
DROP // clean the stack before returning results.
```

As we can see, the usages of `get`

and `set`

is verbose with `swap`

and `dup`

,
it is for adapting any usages but not necessary for all of them, however, we
will introduce optimizer for this in `v0.4.0`

!