diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-02-18 09:11:17 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-02-18 09:11:17 +0100 |
| commit | 4165404f85bf542d5f7a42d81b7288a91a72296d (patch) | |
| tree | 0a25342460cfca9da700dc81cfc22c8160c1452e /src/helpers | |
| parent | 6e6ee64bb4cf10a98c7bd92e06090502eb67e402 (diff) | |
| download | snake.s-4165404f85bf542d5f7a42d81b7288a91a72296d.tar.xz snake.s-4165404f85bf542d5f7a42d81b7288a91a72296d.zip | |
feat: extract some function helpers
Diffstat (limited to 'src/helpers')
| -rw-r--r-- | src/helpers/function.S | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/helpers/function.S b/src/helpers/function.S new file mode 100644 index 0000000..c6647e9 --- /dev/null +++ b/src/helpers/function.S @@ -0,0 +1,108 @@ +.set _FUNCTION_IS_IN_FUNCTION_DEFINITION, 0 +.set _FUNCTION_LOCALS_ALLOCATED, 0 + +.macro _function_local_variable scope, name, size + .if _FUNCTION_IS_IN_FUNCTION_DEFINITION == 0 + .error "Cannot define a local variable outside of a function." + .else + .set _FRAME_OFFSET, _FRAME_OFFSET + \size + .equ \scope\()_name, -_FRAME_OFFSET + .endif +.endm + +.macro _function_allocate_local_variables scope + .if _FUNCTION_IS_IN_FUNCTION_DEFINITION == 0 + .error "Cannot allocate local variables outside of a function." + .elseif _FUNCTION_LOCALS_ALLOCATED == 1 + .error "Local variables have already been allocated." + .else + .set _FUNCTION_LOCALS_ALLOCATED, 1 + .equ \scope\()_FRAME_SIZE, (_FRAME_OFFSET + 15) & -16 + .if \scope\()_FRAME_SIZE > 0 + sub $\scope\()_FRAME_SIZE, %rsp + .endif + .endif +.endm + +.macro _function_load_local scope, name, register + .if _FUNCTION_IS_IN_FUNCTION_DEFINITION == 0 + .error "Cannot load a local variable outside of a function." + .elseif _FUNCTION_LOCALS_ALLOCATED == 0 + .error "Local variables have not been allocated." + .else + mov \scope\()_name(%rbp), \register + .endif +.endm + +.macro _function_store_local scope, register, name + .if _FUNCTION_IS_IN_FUNCTION_DEFINITION == 0 + .error "Cannot store a local variable outside of a function." + .elseif _FUNCTION_LOCALS_ALLOCATED == 0 + .error "Local variables have not been allocated." + .else + mov \register, \scope\()_name(%rbp) + .endif +.endm + +.macro function_begin name + .if _FUNCTION_IS_IN_FUNCTION_DEFINITION == 1 + .error "Cannot define a function inside of another function." + .endif + + .set _FUNCTION_IS_IN_FUNCTION_DEFINITION, 1 + .set _FUNCTION_LOCALS_ALLOCATED, 0 + + .macro define_local var_name, var_size + _function_local_variable \name, \var_name, \var_size + .endm + + .macro allocate_locals + _function_allocate_local_variables \name + .endm + + .macro load_local var_name, register + _function_load_local \name, \var_name, \register + .endm + + .macro store_local register, var_name + _function_store_local \name, \register, \var_name + .endm + + .macro function_exit + jmp .Lexit_\name + .endm + + .macro function_end + .if _FRAME_OFFSET > 0 + .if _FUNCTION_LOCALS_ALLOCATED == 0 + .error "Local variables were never been allocated." + .endif + .endif + + .Lexit_\name: + leave + .cfi_def_cfa %rsp, 8 + ret + .cfi_endproc + .size \name, .-\name + .set _FUNCTION_IS_IN_FUNCTION_DEFINITION, 0 + .set _FUNCTION_LOCALS_ALLOCATED, 0 + .purgem allocate_locals + .purgem function_end + .purgem function_exit + .purgem load_local + .purgem define_local + .purgem store_local + .endm + + .globl \name + .type \name, @function + \name: + .cfi_startproc + push %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + mov %rsp, %rbp + .cfi_def_cfa_register %rbp + .set _FRAME_OFFSET, 0 +.endm |
