clean up (system vm frames), add locals command to debugger
[bpt/guile.git] / libguile / frames.c
1 /* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include "_scm.h"
26 #include "vm-bootstrap.h"
27 #include "frames.h"
28
29 \f
30 scm_t_bits scm_tc16_frame;
31
32 #define RELOC(frame, val) (val + SCM_VM_FRAME_OFFSET (frame))
33
34 SCM
35 scm_c_make_frame (SCM stack_holder, SCM *fp, SCM *sp,
36 scm_t_uint8 *ip, scm_t_ptrdiff offset)
37 {
38 struct scm_frame *p = scm_gc_malloc (sizeof (struct scm_frame),
39 "vmframe");
40 p->stack_holder = stack_holder;
41 p->fp = fp;
42 p->sp = sp;
43 p->ip = ip;
44 p->offset = offset;
45 SCM_RETURN_NEWSMOB (scm_tc16_frame, p);
46 }
47
48 static int
49 frame_print (SCM frame, SCM port, scm_print_state *pstate)
50 {
51 scm_puts ("#<frame ", port);
52 scm_uintprint (SCM_UNPACK (frame), 16, port);
53 scm_putc (' ', port);
54 scm_write (scm_frame_procedure (frame), port);
55 /* don't write args, they can get us into trouble. */
56 scm_puts (">", port);
57
58 return 1;
59 }
60
61 \f
62 /* Scheme interface */
63
64 SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
65 (SCM obj),
66 "")
67 #define FUNC_NAME s_scm_frame_p
68 {
69 return scm_from_bool (SCM_VM_FRAME_P (obj));
70 }
71 #undef FUNC_NAME
72
73 SCM_DEFINE (scm_frame_procedure, "frame-procedure", 1, 0, 0,
74 (SCM frame),
75 "")
76 #define FUNC_NAME s_scm_frame_procedure
77 {
78 SCM_VALIDATE_VM_FRAME (1, frame);
79 return SCM_FRAME_PROGRAM (SCM_VM_FRAME_FP (frame));
80 }
81 #undef FUNC_NAME
82
83 SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
84 (SCM frame),
85 "")
86 #define FUNC_NAME s_scm_frame_arguments
87 {
88 static SCM var = SCM_BOOL_F;
89
90 SCM_VALIDATE_VM_FRAME (1, frame);
91
92 if (scm_is_false (var))
93 var = scm_c_module_lookup (scm_c_resolve_module ("system vm frame"),
94 "frame-arguments");
95
96 return scm_call_1 (SCM_VARIABLE_REF (var), frame);
97 }
98 #undef FUNC_NAME
99
100 SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
101 (SCM frame),
102 "")
103 #define FUNC_NAME s_scm_frame_source
104 {
105 SCM *fp;
106 struct scm_objcode *bp;
107
108 SCM_VALIDATE_VM_FRAME (1, frame);
109
110 fp = SCM_VM_FRAME_FP (frame);
111 bp = SCM_PROGRAM_DATA (SCM_FRAME_PROGRAM (fp));
112
113 return scm_c_program_source (SCM_FRAME_PROGRAM (fp),
114 SCM_VM_FRAME_IP (frame)
115 - SCM_C_OBJCODE_BASE (bp));
116 }
117 #undef FUNC_NAME
118
119 /* The number of locals would be a simple thing to compute, if it weren't for
120 the presence of not-yet-active frames on the stack. So we have a cheap
121 heuristic to detect not-yet-active frames, and skip over them. Perhaps we
122 should represent them more usefully.
123 */
124 SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
125 (SCM frame),
126 "")
127 #define FUNC_NAME s_scm_frame_num_locals
128 {
129 SCM *sp, *p;
130 unsigned int n = 0;
131
132 SCM_VALIDATE_VM_FRAME (1, frame);
133
134 sp = SCM_VM_FRAME_SP (frame);
135 p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
136 while (p <= sp)
137 {
138 if (p + 1 < sp && p[1] == (SCM)0)
139 /* skip over not-yet-active frame */
140 p += 3;
141 else
142 {
143 p++;
144 n++;
145 }
146 }
147 return scm_from_uint (n);
148 }
149 #undef FUNC_NAME
150
151 /* Need same not-yet-active frame logic here as in frame-num-locals */
152 SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
153 (SCM frame, SCM index),
154 "")
155 #define FUNC_NAME s_scm_frame_local_ref
156 {
157 SCM *sp, *p;
158 unsigned int n = 0;
159 unsigned int i;
160
161 SCM_VALIDATE_VM_FRAME (1, frame);
162 SCM_VALIDATE_UINT_COPY (2, index, i);
163
164 sp = SCM_VM_FRAME_SP (frame);
165 p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
166 while (p <= sp)
167 {
168 if (p + 1 < sp && p[1] == (SCM)0)
169 /* skip over not-yet-active frame */
170 p += 3;
171 else if (n == i)
172 return *p;
173 else
174 {
175 p++;
176 n++;
177 }
178 }
179 SCM_OUT_OF_RANGE (SCM_ARG2, index);
180 }
181 #undef FUNC_NAME
182
183 /* Need same not-yet-active frame logic here as in frame-num-locals */
184 SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
185 (SCM frame, SCM index, SCM val),
186 "")
187 #define FUNC_NAME s_scm_frame_local_set_x
188 {
189 SCM *sp, *p;
190 unsigned int n = 0;
191 unsigned int i;
192
193 SCM_VALIDATE_VM_FRAME (1, frame);
194 SCM_VALIDATE_UINT_COPY (2, index, i);
195
196 sp = SCM_VM_FRAME_SP (frame);
197 p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
198 while (p <= sp)
199 {
200 if (p + 1 < sp && p[1] == (SCM)0)
201 /* skip over not-yet-active frame */
202 p += 3;
203 else if (n == i)
204 {
205 *p = val;
206 return SCM_UNSPECIFIED;
207 }
208 else
209 {
210 p++;
211 n++;
212 }
213 }
214 SCM_OUT_OF_RANGE (SCM_ARG2, index);
215 }
216 #undef FUNC_NAME
217
218 SCM_DEFINE (scm_frame_instruction_pointer, "frame-instruction-pointer", 1, 0, 0,
219 (SCM frame),
220 "")
221 #define FUNC_NAME s_scm_frame_instruction_pointer
222 {
223 const struct scm_objcode *c_objcode;
224
225 SCM_VALIDATE_VM_FRAME (1, frame);
226
227 c_objcode = SCM_PROGRAM_DATA (scm_frame_procedure (frame));
228 return scm_from_ulong ((unsigned long)
229 (SCM_VM_FRAME_IP (frame)
230 - SCM_C_OBJCODE_BASE (c_objcode)));
231 }
232 #undef FUNC_NAME
233
234 SCM_DEFINE (scm_frame_return_address, "frame-return-address", 1, 0, 0,
235 (SCM frame),
236 "")
237 #define FUNC_NAME s_scm_frame_return_address
238 {
239 SCM_VALIDATE_VM_FRAME (1, frame);
240 return scm_from_ulong ((unsigned long)
241 (SCM_FRAME_RETURN_ADDRESS
242 (SCM_VM_FRAME_FP (frame))));
243 }
244 #undef FUNC_NAME
245
246 SCM_DEFINE (scm_frame_mv_return_address, "frame-mv-return-address", 1, 0, 0,
247 (SCM frame),
248 "")
249 #define FUNC_NAME s_scm_frame_mv_return_address
250 {
251 SCM_VALIDATE_VM_FRAME (1, frame);
252 return scm_from_ulong ((unsigned long)
253 (SCM_FRAME_MV_RETURN_ADDRESS
254 (SCM_VM_FRAME_FP (frame))));
255 }
256 #undef FUNC_NAME
257
258 SCM_DEFINE (scm_frame_dynamic_link, "frame-dynamic-link", 1, 0, 0,
259 (SCM frame),
260 "")
261 #define FUNC_NAME s_scm_frame_dynamic_link
262 {
263 SCM_VALIDATE_VM_FRAME (1, frame);
264 /* fixme: munge fp if holder is a continuation */
265 return scm_from_ulong
266 ((unsigned long)
267 RELOC (frame,
268 SCM_FRAME_DYNAMIC_LINK (SCM_VM_FRAME_FP (frame))));
269 }
270 #undef FUNC_NAME
271
272 SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
273 (SCM frame),
274 "")
275 #define FUNC_NAME s_scm_frame_previous
276 {
277 SCM *this_fp, *new_fp, *new_sp;
278
279 SCM_VALIDATE_VM_FRAME (1, frame);
280
281 again:
282 this_fp = SCM_VM_FRAME_FP (frame);
283 new_fp = SCM_FRAME_DYNAMIC_LINK (this_fp);
284 if (new_fp)
285 { new_fp = RELOC (frame, new_fp);
286 new_sp = SCM_FRAME_LOWER_ADDRESS (this_fp) - 1;
287 frame = scm_c_make_frame (SCM_VM_FRAME_STACK_HOLDER (frame),
288 new_fp, new_sp,
289 SCM_FRAME_RETURN_ADDRESS (this_fp),
290 SCM_VM_FRAME_OFFSET (frame));
291 if (SCM_PROGRAM_IS_BOOT (scm_frame_procedure (frame)))
292 goto again;
293 else
294 return frame;
295 }
296 else
297 return SCM_BOOL_F;
298 }
299 #undef FUNC_NAME
300
301 \f
302 void
303 scm_bootstrap_frames (void)
304 {
305 scm_tc16_frame = scm_make_smob_type ("frame", 0);
306 scm_set_smob_print (scm_tc16_frame, frame_print);
307 }
308
309 void
310 scm_init_frames (void)
311 {
312 #ifndef SCM_MAGIC_SNARFER
313 #include "libguile/frames.x"
314 #endif
315 }
316
317 /*
318 Local Variables:
319 c-file-style: "gnu"
320 End:
321 */