aboutsummaryrefslogtreecommitdiff
path: root/src/helpers/function.S
blob: c6647e9d0c0f63df45318dcaa61e9e89271a7226 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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