OLD | NEW |
1 /* alloca.c -- allocate automatically reclaimed memory | 1 /* alloca.c -- allocate automatically reclaimed memory |
2 (Mostly) portable public-domain implementation -- D A Gwyn | 2 (Mostly) portable public-domain implementation -- D A Gwyn |
3 | 3 |
4 This implementation of the PWB library alloca function, | 4 This implementation of the PWB library alloca function, |
5 which is used to allocate space off the run-time stack so | 5 which is used to allocate space off the run-time stack so |
6 that it is automatically reclaimed upon procedure exit, | 6 that it is automatically reclaimed upon procedure exit, |
7 was inspired by discussions with J. Q. Johnson of Cornell. | 7 was inspired by discussions with J. Q. Johnson of Cornell. |
8 J.Otto Tennant <jot@cray.com> contributed the Cray support. | 8 J.Otto Tennant <jot@cray.com> contributed the Cray support. |
9 | 9 |
10 There are some preprocessor constants that can | 10 There are some preprocessor constants that can |
11 be defined when compiling for your specific system, for | 11 be defined when compiling for your specific system, for |
12 improved efficiency; however, the defaults should be okay. | 12 improved efficiency; however, the defaults should be okay. |
13 | 13 |
14 The general concept of this implementation is to keep | 14 The general concept of this implementation is to keep |
15 track of all alloca-allocated blocks, and reclaim any | 15 track of all alloca-allocated blocks, and reclaim any |
16 that are found to be deeper in the stack than the current | 16 that are found to be deeper in the stack than the current |
17 invocation. This heuristic does not reclaim storage as | 17 invocation. This heuristic does not reclaim storage as |
18 soon as it becomes invalid, but it will do so eventually. | 18 soon as it becomes invalid, but it will do so eventually. |
19 | 19 |
20 As a special case, alloca(0) reclaims storage without | 20 As a special case, alloca(0) reclaims storage without |
21 allocating any. It is a good idea to use alloca(0) in | 21 allocating any. It is a good idea to use alloca(0) in |
22 your main control loop, etc. to force garbage collection. */ | 22 your main control loop, etc. to force garbage collection. */ |
23 | 23 |
24 /* | 24 #include <config.h> |
25 | 25 |
26 @deftypefn Replacement void* alloca (size_t @var{size}) | 26 #include <alloca.h> |
27 | 27 |
28 This function allocates memory which will be automatically reclaimed | 28 #include <string.h> |
29 after the procedure exits. The @libib{} implementation does not free | 29 #include <stdlib.h> |
30 the memory immediately but will do so eventually during subsequent | |
31 calls to this function. Memory is allocated using @code{xmalloc} under | |
32 normal circumstances. | |
33 | 30 |
34 The header file @file{alloca-conf.h} can be used in conjunction with the | 31 #ifdef emacs |
35 GNU Autoconf test @code{AC_FUNC_ALLOCA} to test for and properly make | 32 # include "lisp.h" |
36 available this function. The @code{AC_FUNC_ALLOCA} test requires that | 33 # include "blockinput.h" |
37 client code use a block of preprocessor code to be safe (see the Autoconf | 34 # ifdef EMACS_FREE |
38 manual for more); this header incorporates that logic and more, including | 35 # undef free |
39 the possibility of a GCC built-in function. | 36 # define free EMACS_FREE |
40 | 37 # endif |
41 @end deftypefn | 38 #else |
42 | 39 # define memory_full() abort () |
43 */ | |
44 | |
45 #ifdef HAVE_CONFIG_H | |
46 #include <config.h> | |
47 #endif | 40 #endif |
48 | 41 |
49 #include <libiberty.h> | 42 /* If compiling with GCC 2, this file's not needed. */ |
| 43 #if !defined (__GNUC__) || __GNUC__ < 2 |
50 | 44 |
51 #ifdef HAVE_STRING_H | 45 /* If someone has defined alloca as a macro, |
52 #include <string.h> | 46 there must be some other way alloca is supposed to work. */ |
53 #endif | 47 # ifndef alloca |
54 #ifdef HAVE_STDLIB_H | |
55 #include <stdlib.h> | |
56 #endif | |
57 | 48 |
58 /* These variables are used by the ASTRDUP implementation that relies | 49 # ifdef emacs |
59 on C_alloca. */ | 50 # ifdef static |
60 #ifdef __cplusplus | 51 /* actually, only want this if static is defined as "" |
61 extern "C" { | 52 -- this is for usg, in which emacs must undefine static |
62 #endif /* __cplusplus */ | 53 in order to make unexec workable |
63 const char *libiberty_optr; | 54 */ |
64 char *libiberty_nptr; | 55 # ifndef STACK_DIRECTION |
65 unsigned long libiberty_len; | 56 you |
66 #ifdef __cplusplus | 57 lose |
67 } | 58 -- must know STACK_DIRECTION at compile-time |
68 #endif /* __cplusplus */ | 59 /* Using #error here is not wise since this file should work for |
| 60 old and obscure compilers. */ |
| 61 # endif /* STACK_DIRECTION undefined */ |
| 62 # endif /* static */ |
| 63 # endif /* emacs */ |
69 | 64 |
70 /* If your stack is a linked list of frames, you have to | 65 /* If your stack is a linked list of frames, you have to |
71 provide an "address metric" ADDRESS_FUNCTION macro. */ | 66 provide an "address metric" ADDRESS_FUNCTION macro. */ |
72 | 67 |
73 #if defined (CRAY) && defined (CRAY_STACKSEG_END) | 68 # if defined (CRAY) && defined (CRAY_STACKSEG_END) |
74 static long i00afunc (); | 69 long i00afunc (); |
75 #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) | 70 # define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) |
76 #else | 71 # else |
77 #define ADDRESS_FUNCTION(arg) &(arg) | 72 # define ADDRESS_FUNCTION(arg) &(arg) |
78 #endif | 73 # endif |
79 | |
80 #ifndef NULL | |
81 #define»NULL» 0 | |
82 #endif | |
83 | 74 |
84 /* Define STACK_DIRECTION if you know the direction of stack | 75 /* Define STACK_DIRECTION if you know the direction of stack |
85 growth for your system; otherwise it will be automatically | 76 growth for your system; otherwise it will be automatically |
86 deduced at run-time. | 77 deduced at run-time. |
87 | 78 |
88 STACK_DIRECTION > 0 => grows toward higher addresses | 79 STACK_DIRECTION > 0 => grows toward higher addresses |
89 STACK_DIRECTION < 0 => grows toward lower addresses | 80 STACK_DIRECTION < 0 => grows toward lower addresses |
90 STACK_DIRECTION = 0 => direction of growth unknown */ | 81 STACK_DIRECTION = 0 => direction of growth unknown */ |
91 | 82 |
92 #ifndef STACK_DIRECTION | 83 # ifndef STACK_DIRECTION |
93 #define»STACK_DIRECTION»0» /* Direction unknown. */ | 84 # define STACK_DIRECTION 0 /* Direction unknown. */ |
94 #endif | 85 # endif |
95 | 86 |
96 #if STACK_DIRECTION != 0 | 87 # if STACK_DIRECTION != 0 |
97 | 88 |
98 #define»STACK_DIR» STACK_DIRECTION»/* Known at compile-time. */ | 89 # define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ |
99 | 90 |
100 #else /* STACK_DIRECTION == 0; need run-time code. */ | 91 # else /* STACK_DIRECTION == 0; need run-time code. */ |
101 | 92 |
102 static int stack_dir;» » /* 1 or -1 once known. */ | 93 static int stack_dir; /* 1 or -1 once known. */ |
103 #define»STACK_DIR» stack_dir | 94 # define STACK_DIR stack_dir |
104 | 95 |
105 static void | 96 static int |
106 find_stack_direction (void) | 97 find_stack_direction (int *addr, int depth) |
107 { | 98 { |
108 static char *addr = NULL;» /* Address of first `dummy', once known. */ | 99 int dir, dummy = 0; |
109 auto char dummy;» » /* To get stack address. */ | 100 if (! addr) |
110 | 101 addr = &dummy; |
111 if (addr == NULL) | 102 *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; |
112 {» » » » /* Initial entry. */ | 103 dir = depth ? find_stack_direction (addr, depth - 1) : 0; |
113 addr = ADDRESS_FUNCTION (dummy); | 104 return dir + dummy; |
114 | |
115 find_stack_direction ();» /* Recurse once. */ | |
116 } | |
117 else | |
118 { | |
119 /* Second entry. */ | |
120 if (ADDRESS_FUNCTION (dummy) > addr) | |
121 » stack_dir = 1;» » /* Stack grew upward. */ | |
122 else | |
123 » stack_dir = -1;»» /* Stack grew downward. */ | |
124 } | |
125 } | 105 } |
126 | 106 |
127 #endif /* STACK_DIRECTION == 0 */ | 107 # endif /* STACK_DIRECTION == 0 */ |
128 | 108 |
129 /* An "alloca header" is used to: | 109 /* An "alloca header" is used to: |
130 (a) chain together all alloca'ed blocks; | 110 (a) chain together all alloca'ed blocks; |
131 (b) keep track of stack depth. | 111 (b) keep track of stack depth. |
132 | 112 |
133 It is very important that sizeof(header) agree with malloc | 113 It is very important that sizeof(header) agree with malloc |
134 alignment chunk size. The following default should work okay. */ | 114 alignment chunk size. The following default should work okay. */ |
135 | 115 |
136 #ifndef»ALIGN_SIZE | 116 # ifndef ALIGN_SIZE |
137 #define»ALIGN_SIZE» sizeof(double) | 117 # define ALIGN_SIZE sizeof(double) |
138 #endif | 118 # endif |
139 | 119 |
140 typedef union hdr | 120 typedef union hdr |
141 { | 121 { |
142 char align[ALIGN_SIZE];» /* To force sizeof(header). */ | 122 char align[ALIGN_SIZE]; /* To force sizeof(header). */ |
143 struct | 123 struct |
144 { | 124 { |
145 union hdr *next;» » /* For chaining headers. */ | 125 union hdr *next; /* For chaining headers. */ |
146 char *deep;» » /* For stack depth measure. */ | 126 char *deep; /* For stack depth measure. */ |
147 } h; | 127 } h; |
148 } header; | 128 } header; |
149 | 129 |
150 static header *last_alloca_header = NULL;» /* -> last alloca header. */ | 130 static header *last_alloca_header = NULL; /* -> last alloca header. */ |
151 | 131 |
152 /* Return a pointer to at least SIZE bytes of storage, | 132 /* Return a pointer to at least SIZE bytes of storage, |
153 which will be automatically reclaimed upon exit from | 133 which will be automatically reclaimed upon exit from |
154 the procedure that called alloca. Originally, this space | 134 the procedure that called alloca. Originally, this space |
155 was supposed to be taken from the current stack frame of the | 135 was supposed to be taken from the current stack frame of the |
156 caller, but that method cannot be made to work for some | 136 caller, but that method cannot be made to work for some |
157 implementations of C, for example under Gould's UTX/32. */ | 137 implementations of C, for example under Gould's UTX/32. */ |
158 | 138 |
159 /* @undocumented C_alloca */ | 139 void * |
160 | 140 alloca (size_t size) |
161 PTR | |
162 C_alloca (size_t size) | |
163 { | 141 { |
164 auto char probe;» » /* Probes stack depth: */ | 142 auto char probe; /* Probes stack depth: */ |
165 register char *depth = ADDRESS_FUNCTION (probe); | 143 register char *depth = ADDRESS_FUNCTION (probe); |
166 | 144 |
167 #if STACK_DIRECTION == 0 | 145 # if STACK_DIRECTION == 0 |
168 if (STACK_DIR == 0)» » /* Unknown growth direction. */ | 146 if (STACK_DIR == 0) /* Unknown growth direction. */ |
169 find_stack_direction (); | 147 STACK_DIR = find_stack_direction (NULL, (size & 1) + 20); |
170 #endif | 148 # endif |
171 | 149 |
172 /* Reclaim garbage, defined as all alloca'd storage that | 150 /* Reclaim garbage, defined as all alloca'd storage that |
173 was allocated from deeper in the stack than currently. */ | 151 was allocated from deeper in the stack than currently. */ |
174 | 152 |
175 { | 153 { |
176 register header *hp;» /* Traverses linked list. */ | 154 register header *hp; /* Traverses linked list. */ |
| 155 |
| 156 # ifdef emacs |
| 157 BLOCK_INPUT; |
| 158 # endif |
177 | 159 |
178 for (hp = last_alloca_header; hp != NULL;) | 160 for (hp = last_alloca_header; hp != NULL;) |
179 if ((STACK_DIR > 0 && hp->h.deep > depth) | 161 if ((STACK_DIR > 0 && hp->h.deep > depth) |
180 » || (STACK_DIR < 0 && hp->h.deep < depth)) | 162 || (STACK_DIR < 0 && hp->h.deep < depth)) |
181 » { | 163 { |
182 » register header *np = hp->h.next; | 164 register header *np = hp->h.next; |
183 | 165 |
184 » free ((PTR) hp);» /* Collect garbage. */ | 166 free (hp); /* Collect garbage. */ |
185 | 167 |
186 » hp = np;» » /* -> next header. */ | 168 hp = np; /* -> next header. */ |
187 » } | 169 } |
188 else | 170 else |
189 » break;» » » /* Rest are not deeper. */ | 171 break; /* Rest are not deeper. */ |
190 | 172 |
191 last_alloca_header = hp;» /* -> last valid storage. */ | 173 last_alloca_header = hp; /* -> last valid storage. */ |
| 174 |
| 175 # ifdef emacs |
| 176 UNBLOCK_INPUT; |
| 177 # endif |
192 } | 178 } |
193 | 179 |
194 if (size == 0) | 180 if (size == 0) |
195 return NULL;» » /* No allocation required. */ | 181 return NULL; /* No allocation required. */ |
196 | 182 |
197 /* Allocate combined header + user data storage. */ | 183 /* Allocate combined header + user data storage. */ |
198 | 184 |
199 { | 185 { |
200 register void *new_storage = XNEWVEC (char, sizeof (header) + size); | |
201 /* Address of header. */ | 186 /* Address of header. */ |
| 187 register header *new; |
202 | 188 |
203 if (new_storage == 0) | 189 size_t combined_size = sizeof (header) + size; |
204 abort(); | 190 if (combined_size < sizeof (header)) |
| 191 memory_full (); |
205 | 192 |
206 ((header *) new_storage)->h.next = last_alloca_header; | 193 new = malloc (combined_size); |
207 ((header *) new_storage)->h.deep = depth; | |
208 | 194 |
209 last_alloca_header = (header *) new_storage; | 195 if (! new) |
| 196 memory_full (); |
| 197 |
| 198 new->h.next = last_alloca_header; |
| 199 new->h.deep = depth; |
| 200 |
| 201 last_alloca_header = new; |
210 | 202 |
211 /* User storage begins just after header. */ | 203 /* User storage begins just after header. */ |
212 | 204 |
213 return (PTR) ((char *) new_storage + sizeof (header)); | 205 return (void *) (new + 1); |
214 } | 206 } |
215 } | 207 } |
216 | 208 |
217 #if defined (CRAY) && defined (CRAY_STACKSEG_END) | 209 # if defined (CRAY) && defined (CRAY_STACKSEG_END) |
218 | 210 |
219 #ifdef DEBUG_I00AFUNC | 211 # ifdef DEBUG_I00AFUNC |
220 #include <stdio.h> | 212 # include <stdio.h> |
221 #endif | 213 # endif |
222 | 214 |
223 #ifndef CRAY_STACK | 215 # ifndef CRAY_STACK |
224 #define CRAY_STACK | 216 # define CRAY_STACK |
225 #ifndef CRAY2 | 217 # ifndef CRAY2 |
226 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ | 218 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ |
227 struct stack_control_header | 219 struct stack_control_header |
228 { | 220 { |
229 long shgrow:32;» » /* Number of times stack has grown. */ | 221 long shgrow:32; /* Number of times stack has grown. */ |
230 long shaseg:32;» » /* Size of increments to stack. */ | 222 long shaseg:32; /* Size of increments to stack. */ |
231 long shhwm:32;» » /* High water mark of stack. */ | 223 long shhwm:32; /* High water mark of stack. */ |
232 long shsize:32;» » /* Current size of stack (all segments). */ | 224 long shsize:32; /* Current size of stack (all segments). */ |
233 }; | 225 }; |
234 | 226 |
235 /* The stack segment linkage control information occurs at | 227 /* The stack segment linkage control information occurs at |
236 the high-address end of a stack segment. (The stack | 228 the high-address end of a stack segment. (The stack |
237 grows from low addresses to high addresses.) The initial | 229 grows from low addresses to high addresses.) The initial |
238 part of the stack segment linkage control information is | 230 part of the stack segment linkage control information is |
239 0200 (octal) words. This provides for register storage | 231 0200 (octal) words. This provides for register storage |
240 for the routine which overflows the stack. */ | 232 for the routine which overflows the stack. */ |
241 | 233 |
242 struct stack_segment_linkage | 234 struct stack_segment_linkage |
243 { | 235 { |
244 long ss[0200];» » /* 0200 overflow words. */ | 236 long ss[0200]; /* 0200 overflow words. */ |
245 long sssize:32;» » /* Number of words in this segment. */ | 237 long sssize:32; /* Number of words in this segment. */ |
246 long ssbase:32;» » /* Offset to stack base. */ | 238 long ssbase:32; /* Offset to stack base. */ |
247 long:32; | 239 long:32; |
248 long sspseg:32;» » /* Offset to linkage control of previous | 240 long sspseg:32; /* Offset to linkage control of previous |
249 » » » » segment of stack. */ | 241 segment of stack. */ |
250 long:32; | 242 long:32; |
251 long sstcpt:32;» » /* Pointer to task common address block. */ | 243 long sstcpt:32; /* Pointer to task common address block. */ |
252 long sscsnm;» » /* Private control structure number for | 244 long sscsnm; /* Private control structure number for |
253 » » » » microtasking. */ | 245 microtasking. */ |
254 long ssusr1;» » /* Reserved for user. */ | 246 long ssusr1; /* Reserved for user. */ |
255 long ssusr2;» » /* Reserved for user. */ | 247 long ssusr2; /* Reserved for user. */ |
256 long sstpid;» » /* Process ID for pid based multi-tasking. */ | 248 long sstpid; /* Process ID for pid based multi-tasking. */ |
257 long ssgvup;» » /* Pointer to multitasking thread giveup. */ | 249 long ssgvup; /* Pointer to multitasking thread giveup. */ |
258 long sscray[7];» » /* Reserved for Cray Research. */ | 250 long sscray[7]; /* Reserved for Cray Research. */ |
259 long ssa0; | 251 long ssa0; |
260 long ssa1; | 252 long ssa1; |
261 long ssa2; | 253 long ssa2; |
262 long ssa3; | 254 long ssa3; |
263 long ssa4; | 255 long ssa4; |
264 long ssa5; | 256 long ssa5; |
265 long ssa6; | 257 long ssa6; |
266 long ssa7; | 258 long ssa7; |
267 long sss0; | 259 long sss0; |
268 long sss1; | 260 long sss1; |
269 long sss2; | 261 long sss2; |
270 long sss3; | 262 long sss3; |
271 long sss4; | 263 long sss4; |
272 long sss5; | 264 long sss5; |
273 long sss6; | 265 long sss6; |
274 long sss7; | 266 long sss7; |
275 }; | 267 }; |
276 | 268 |
277 #else /* CRAY2 */ | 269 # else /* CRAY2 */ |
278 /* The following structure defines the vector of words | 270 /* The following structure defines the vector of words |
279 returned by the STKSTAT library routine. */ | 271 returned by the STKSTAT library routine. */ |
280 struct stk_stat | 272 struct stk_stat |
281 { | 273 { |
282 long now;» » » /* Current total stack size. */ | 274 long now; /* Current total stack size. */ |
283 long maxc;» » » /* Amount of contiguous space which would | 275 long maxc; /* Amount of contiguous space which would |
284 » » » » be required to satisfy the maximum | 276 be required to satisfy the maximum |
285 » » » » stack demand to date. */ | 277 stack demand to date. */ |
286 long high_water;» » /* Stack high-water mark. */ | 278 long high_water; /* Stack high-water mark. */ |
287 long overflows;» » /* Number of stack overflow ($STKOFEN) calls. *
/ | 279 long overflows; /* Number of stack overflow ($STKOFEN) calls. *
/ |
288 long hits;» » » /* Number of internal buffer hits. */ | 280 long hits; /* Number of internal buffer hits. */ |
289 long extends;» » /* Number of block extensions. */ | 281 long extends; /* Number of block extensions. */ |
290 long stko_mallocs;» » /* Block allocations by $STKOFEN. */ | 282 long stko_mallocs; /* Block allocations by $STKOFEN. */ |
291 long underflows;» » /* Number of stack underflow calls ($STKRETN).
*/ | 283 long underflows; /* Number of stack underflow calls ($STKRETN).
*/ |
292 long stko_free;» » /* Number of deallocations by $STKRETN. */ | 284 long stko_free; /* Number of deallocations by $STKRETN. */ |
293 long stkm_free;» » /* Number of deallocations by $STKMRET. */ | 285 long stkm_free; /* Number of deallocations by $STKMRET. */ |
294 long segments;» » /* Current number of stack segments. */ | 286 long segments; /* Current number of stack segments. */ |
295 long maxs;» » » /* Maximum number of stack segments so far. */ | 287 long maxs; /* Maximum number of stack segments so far. */ |
296 long pad_size;» » /* Stack pad size. */ | 288 long pad_size; /* Stack pad size. */ |
297 long current_address;» /* Current stack segment address. */ | 289 long current_address; /* Current stack segment address. */ |
298 long current_size;» » /* Current stack segment size. This | 290 long current_size; /* Current stack segment size. This |
299 » » » » number is actually corrupted by STKSTAT to | 291 number is actually corrupted by STKSTAT to |
300 » » » » include the fifteen word trailer area. */ | 292 include the fifteen word trailer area. */ |
301 long initial_address;» /* Address of initial segment. */ | 293 long initial_address; /* Address of initial segment. */ |
302 long initial_size;» » /* Size of initial segment. */ | 294 long initial_size; /* Size of initial segment. */ |
303 }; | 295 }; |
304 | 296 |
305 /* The following structure describes the data structure which trails | 297 /* The following structure describes the data structure which trails |
306 any stack segment. I think that the description in 'asdef' is | 298 any stack segment. I think that the description in 'asdef' is |
307 out of date. I only describe the parts that I am sure about. */ | 299 out of date. I only describe the parts that I am sure about. */ |
308 | 300 |
309 struct stk_trailer | 301 struct stk_trailer |
310 { | 302 { |
311 long this_address;» » /* Address of this block. */ | 303 long this_address; /* Address of this block. */ |
312 long this_size;» » /* Size of this block (does not include | 304 long this_size; /* Size of this block (does not include |
313 » » » » this trailer). */ | 305 this trailer). */ |
314 long unknown2; | 306 long unknown2; |
315 long unknown3; | 307 long unknown3; |
316 long link;» » » /* Address of trailer block of previous | 308 long link; /* Address of trailer block of previous |
317 » » » » segment. */ | 309 segment. */ |
318 long unknown5; | 310 long unknown5; |
319 long unknown6; | 311 long unknown6; |
320 long unknown7; | 312 long unknown7; |
321 long unknown8; | 313 long unknown8; |
322 long unknown9; | 314 long unknown9; |
323 long unknown10; | 315 long unknown10; |
324 long unknown11; | 316 long unknown11; |
325 long unknown12; | 317 long unknown12; |
326 long unknown13; | 318 long unknown13; |
327 long unknown14; | 319 long unknown14; |
328 }; | 320 }; |
329 | 321 |
330 #endif /* CRAY2 */ | 322 # endif /* CRAY2 */ |
331 #endif /* not CRAY_STACK */ | 323 # endif /* not CRAY_STACK */ |
332 | 324 |
333 #ifdef CRAY2 | 325 # ifdef CRAY2 |
334 /* Determine a "stack measure" for an arbitrary ADDRESS. | 326 /* Determine a "stack measure" for an arbitrary ADDRESS. |
335 I doubt that "lint" will like this much. */ | 327 I doubt that "lint" will like this much. */ |
336 | 328 |
337 static long | 329 static long |
338 i00afunc (long *address) | 330 i00afunc (long *address) |
339 { | 331 { |
340 struct stk_stat status; | 332 struct stk_stat status; |
341 struct stk_trailer *trailer; | 333 struct stk_trailer *trailer; |
342 long *block, size; | 334 long *block, size; |
343 long result = 0; | 335 long result = 0; |
344 | 336 |
345 /* We want to iterate through all of the segments. The first | 337 /* We want to iterate through all of the segments. The first |
346 step is to get the stack status structure. We could do this | 338 step is to get the stack status structure. We could do this |
347 more quickly and more directly, perhaps, by referencing the | 339 more quickly and more directly, perhaps, by referencing the |
348 $LM00 common block, but I know that this works. */ | 340 $LM00 common block, but I know that this works. */ |
349 | 341 |
350 STKSTAT (&status); | 342 STKSTAT (&status); |
351 | 343 |
352 /* Set up the iteration. */ | 344 /* Set up the iteration. */ |
353 | 345 |
354 trailer = (struct stk_trailer *) (status.current_address | 346 trailer = (struct stk_trailer *) (status.current_address |
355 » » » » + status.current_size | 347 + status.current_size |
356 » » » » - 15); | 348 - 15); |
357 | 349 |
358 /* There must be at least one stack segment. Therefore it is | 350 /* There must be at least one stack segment. Therefore it is |
359 a fatal error if "trailer" is null. */ | 351 a fatal error if "trailer" is null. */ |
360 | 352 |
361 if (trailer == 0) | 353 if (trailer == 0) |
362 abort (); | 354 abort (); |
363 | 355 |
364 /* Discard segments that do not contain our argument address. */ | 356 /* Discard segments that do not contain our argument address. */ |
365 | 357 |
366 while (trailer != 0) | 358 while (trailer != 0) |
367 { | 359 { |
368 block = (long *) trailer->this_address; | 360 block = (long *) trailer->this_address; |
369 size = trailer->this_size; | 361 size = trailer->this_size; |
370 if (block == 0 || size == 0) | 362 if (block == 0 || size == 0) |
371 » abort (); | 363 abort (); |
372 trailer = (struct stk_trailer *) trailer->link; | 364 trailer = (struct stk_trailer *) trailer->link; |
373 if ((block <= address) && (address < (block + size))) | 365 if ((block <= address) && (address < (block + size))) |
374 » break; | 366 break; |
375 } | 367 } |
376 | 368 |
377 /* Set the result to the offset in this segment and add the sizes | 369 /* Set the result to the offset in this segment and add the sizes |
378 of all predecessor segments. */ | 370 of all predecessor segments. */ |
379 | 371 |
380 result = address - block; | 372 result = address - block; |
381 | 373 |
382 if (trailer == 0) | 374 if (trailer == 0) |
383 { | 375 { |
384 return result; | 376 return result; |
385 } | 377 } |
386 | 378 |
387 do | 379 do |
388 { | 380 { |
389 if (trailer->this_size <= 0) | 381 if (trailer->this_size <= 0) |
390 » abort (); | 382 abort (); |
391 result += trailer->this_size; | 383 result += trailer->this_size; |
392 trailer = (struct stk_trailer *) trailer->link; | 384 trailer = (struct stk_trailer *) trailer->link; |
393 } | 385 } |
394 while (trailer != 0); | 386 while (trailer != 0); |
395 | 387 |
396 /* We are done. Note that if you present a bogus address (one | 388 /* We are done. Note that if you present a bogus address (one |
397 not in any segment), you will get a different number back, formed | 389 not in any segment), you will get a different number back, formed |
398 from subtracting the address of the first block. This is probably | 390 from subtracting the address of the first block. This is probably |
399 not what you want. */ | 391 not what you want. */ |
400 | 392 |
401 return (result); | 393 return (result); |
402 } | 394 } |
403 | 395 |
404 #else /* not CRAY2 */ | 396 # else /* not CRAY2 */ |
405 /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. | 397 /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. |
406 Determine the number of the cell within the stack, | 398 Determine the number of the cell within the stack, |
407 given the address of the cell. The purpose of this | 399 given the address of the cell. The purpose of this |
408 routine is to linearize, in some sense, stack addresses | 400 routine is to linearize, in some sense, stack addresses |
409 for alloca. */ | 401 for alloca. */ |
410 | 402 |
411 static long | 403 static long |
412 i00afunc (long address) | 404 i00afunc (long address) |
413 { | 405 { |
414 long stkl = 0; | 406 long stkl = 0; |
(...skipping 24 matching lines...) Expand all Loading... |
439 size = ssptr->sssize; | 431 size = ssptr->sssize; |
440 | 432 |
441 this_segment = stkl - size; | 433 this_segment = stkl - size; |
442 | 434 |
443 /* It is possible that calling this routine itself caused | 435 /* It is possible that calling this routine itself caused |
444 a stack overflow. Discard stack segments which do not | 436 a stack overflow. Discard stack segments which do not |
445 contain the target address. */ | 437 contain the target address. */ |
446 | 438 |
447 while (!(this_segment <= address && address <= stkl)) | 439 while (!(this_segment <= address && address <= stkl)) |
448 { | 440 { |
449 #ifdef DEBUG_I00AFUNC | 441 # ifdef DEBUG_I00AFUNC |
450 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); | 442 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); |
451 #endif | 443 # endif |
452 if (pseg == 0) | 444 if (pseg == 0) |
453 » break; | 445 break; |
454 stkl = stkl - pseg; | 446 stkl = stkl - pseg; |
455 ssptr = (struct stack_segment_linkage *) stkl; | 447 ssptr = (struct stack_segment_linkage *) stkl; |
456 size = ssptr->sssize; | 448 size = ssptr->sssize; |
457 pseg = ssptr->sspseg; | 449 pseg = ssptr->sspseg; |
458 this_segment = stkl - size; | 450 this_segment = stkl - size; |
459 } | 451 } |
460 | 452 |
461 result = address - this_segment; | 453 result = address - this_segment; |
462 | 454 |
463 /* If you subtract pseg from the current end of the stack, | 455 /* If you subtract pseg from the current end of the stack, |
464 you get the address of the previous stack segment's end. | 456 you get the address of the previous stack segment's end. |
465 This seems a little convoluted to me, but I'll bet you save | 457 This seems a little convoluted to me, but I'll bet you save |
466 a cycle somewhere. */ | 458 a cycle somewhere. */ |
467 | 459 |
468 while (pseg != 0) | 460 while (pseg != 0) |
469 { | 461 { |
470 #ifdef DEBUG_I00AFUNC | 462 # ifdef DEBUG_I00AFUNC |
471 fprintf (stderr, "%011o %011o\n", pseg, size); | 463 fprintf (stderr, "%011o %011o\n", pseg, size); |
472 #endif | 464 # endif |
473 stkl = stkl - pseg; | 465 stkl = stkl - pseg; |
474 ssptr = (struct stack_segment_linkage *) stkl; | 466 ssptr = (struct stack_segment_linkage *) stkl; |
475 size = ssptr->sssize; | 467 size = ssptr->sssize; |
476 pseg = ssptr->sspseg; | 468 pseg = ssptr->sspseg; |
477 result += size; | 469 result += size; |
478 } | 470 } |
479 return (result); | 471 return (result); |
480 } | 472 } |
481 | 473 |
482 #endif /* not CRAY2 */ | 474 # endif /* not CRAY2 */ |
483 #endif /* CRAY */ | 475 # endif /* CRAY */ |
| 476 |
| 477 # endif /* no alloca */ |
| 478 #endif /* not GCC 2 */ |
OLD | NEW |