-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathstackman.h
More file actions
124 lines (113 loc) · 5.38 KB
/
stackman.h
File metadata and controls
124 lines (113 loc) · 5.38 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#pragma once
#ifndef STACKMAN_H
#define STACKMAN_H
/* Version information */
#define STACKMAN_VERSION_MAJOR 1
#define STACKMAN_VERSION_MINOR 2
#define STACKMAN_VERSION_PATCH 0
/* Version as a string */
#define STACKMAN_VERSION "1.2.0"
/* Version as a single number for comparisons (MMmmpp: Major, minor, patch) */
#define STACKMAN_VERSION_NUMBER ((STACKMAN_VERSION_MAJOR * 10000) + \
(STACKMAN_VERSION_MINOR * 100) + \
STACKMAN_VERSION_PATCH)
/* the main include file. The following macros can be defined before including
* STACKMAN_OPTIONAL - Do not error if the platform isn't supported
* STACKMAN_VERBOSE - Emit the found platform to output
* STACKMAN_INLINE_ASM
* - leave undefined or define as 0 to prefer assembly code to inline-assembly (default)
* - define as 1 to prefer inline-assembly. This is recommended only for
* development since compiler versions and implementation details may
* create assembly that is incorrect.
*
* After include, the following may be defined
* STACKMAN_PLATFORM - If defined, the platform in use
* STACKMAN_ABI - the ABI being used.
* STACKMAN_PLATFORM_ASM - If pure assembler, the filename of the assembly code.
*
* For the file providing the implementation of stackman_switch(), include
* "stackman_impl.h" instead.
*/
#include "platforms/platform.h"
#include "stackman_switch.h"
/* The default stack direction is downwards, 0, but platforms
* can redefine it to upwards growing, 1.
* Since we support both architectures with descending and
* ascending stacks, we use the terms "near" and "far"
* to describe stack boundaries. In a typical architecture
* with descending stacks, "near" corresponds to a low
* address and "far" to a high address.
* Also provide defaults for stack "fullness" and alignment. The most
* common stacks are "full" "descending"
*/
#ifndef STACKMAN_STACK_DIR
#define STACKMAN_STACK_DIR 0 /* stack pointer grows "downwards" in memory. */
#endif
#ifndef STACKMAN_STACK_FULL
#define STACKMAN_STACK_FULL 1 /* stack pointer points to a "full" position */
#endif
#ifndef STACKMAN_STACK_ALIGN
#define STACKMAN_STACK_ALIGN 4 /* stack pointer needs to be aligned to this */
#endif
/* define common macros for stack type. Currently only platforms with FULL_DESCENDING are supported. */
#define STACKMAN_STACK_FULL_DESCENDING 0
#define STACKMAN_STACK_EMPTY_DESCENDING 0
#define STACKMAN_STACK_FULL_ASCENDING 0
#define STACKMAN_STACK_EMPTY_ASCENDING 0
#if STACKMAN_STACK_DIR == 0
#if STACKMAN_STACK_FULL == 1
#undef STACKMAN_STACK_FULL_DESCENDING
#define STACKMAN_STACK_FULL_DESCENDING 1
#else
#undef STACKMAN_STACK_EMPTY_DESCENDING
#define STACKMAN_STACK_EMPTY_DESCENDING 1
#endif
#else
#if STACKMAN_STACK_FULL == 0
#undef STACKMAN_STACK_FULL_ASCENDING
#define STACKMAN_STACK_FULL_ASCENDING 1
#else
#undef STACKMAN_STACK_EMPTY_ASCENDING
#define STACKMAN_STACK_EMPTY_ASCENDING 1
#endif
#endif
/* align a stack pointer to the righ alighment, either nudging it up or down */
#define STACKMAN_SP_ALIGN_DOWN(a) (((intptr_t)(a) & ~(STACKMAN_STACK_ALIGN-1)))
#define STACKMAN_SP_ALIGN_UP(a) (((intptr_t)((a)+STACKMAN_STACK_ALIGN-1) & ~(STACKMAN_STACK_ALIGN-1)))
/* Stack pointer manipulation macros that work for both descending and ascending stacks.
*
* STACKMAN_SP_FURTHEST and STACKMAN_SP_NEAREST are sentinel values representing the
* theoretical limits of the stack address space. These should be used for initialization
* and comparison only.
*
* WARNING: Do NOT use STACKMAN_SP_FURTHEST or STACKMAN_SP_NEAREST with STACKMAN_SP_ADD
* or STACKMAN_SP_DIFF operations, as these sentinel values are at the extreme ends of
* the address space and arithmetic operations with them can cause pointer overflow and
* undefined behavior.
*
* Safe operations with FURTHEST/NEAREST: STACKMAN_SP_LS, STACKMAN_SP_LE (comparison)
* Unsafe operations: STACKMAN_SP_ADD, STACKMAN_SP_DIFF (arithmetic)
*
* For actual stack boundaries, use real pointer values (e.g., address of a stack variable).
* The sentinel values can be used instead if the stack bounds are unknown, but then the value
* should always be checked first for the sentinel value before performing any arithmetic operations.
*/
#if STACKMAN_STACK_DIR == 0
#define STACKMAN_SP_FURTHEST ((void*) (intptr_t) -STACKMAN_STACK_ALIGN)
#define STACKMAN_SP_NEAREST ((void*) 0)
#define STACKMAN_SP_LS(a, b) ((void*)(a) < (void*)(b)) /* to compare stack position */
#define STACKMAN_SP_LE(a, b) ((void*)(a) <= (void*)(b)) /* to compare stack position */
#define STACKMAN_SP_ADD(a, b) ((a) + (b)) /* to add offset to stack pointer */
#define STACKMAN_SP_DIFF(a, b) ((a) - (b)) /* to subtract stack pointers */
#define STACKMAN_SP_ALIGN(a) STACKMAN_SP_ALIGN_DOWN(a)
#else
/* upwards growing stacks */
#define STACKMAN_SP_FURTHEST ((void*) 0)
#define STACKMAN_SP_NEAREST ((void*) (intptr_t) -STACKMAN_STACK_ALIGN)
#define STACKMAN_SP_LS(a, b) ((void*)(a) > (void*)(b)) /* to compare stack position */
#define STACKMAN_SP_LE(a, b) ((void*)(a) >= (void*)(b)) /* to compare stack position */
#define STACKMAN_SP_ADD(a, b) ((a) - (b)) /* to add offset to stack pointer */
#define STACKMAN_SP_DIFF(a, b) ((b) - (a)) /* to subtract stack pointers */
#define STACKMAN_SP_ALIGN(a) STACKMAN_SP_ALIGN_UP(a)
#endif
#endif /* STACKMAN_H */