xref: /csrg-svn/old/dbx/runtime.sun.c (revision 38104)
1*38104Sbostic /*
2*38104Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38104Sbostic  * All rights reserved.
4*38104Sbostic  *
5*38104Sbostic  * Redistribution and use in source and binary forms are permitted
6*38104Sbostic  * provided that the above copyright notice and this paragraph are
7*38104Sbostic  * duplicated in all such forms and that any documentation,
8*38104Sbostic  * advertising materials, and other materials related to such
9*38104Sbostic  * distribution and use acknowledge that the software was developed
10*38104Sbostic  * by the University of California, Berkeley.  The name of the
11*38104Sbostic  * University may not be used to endorse or promote products derived
12*38104Sbostic  * from this software without specific prior written permission.
13*38104Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38104Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38104Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*38104Sbostic  */
17*38104Sbostic 
18*38104Sbostic #ifndef lint
19*38104Sbostic static char sccsid[] = "@(#)runtime.sun.c	5.1 (Berkeley) 05/23/89";
20*38104Sbostic #endif /* not lint */
21*38104Sbostic 
22*38104Sbostic /*
23*38104Sbostic  * Runtime organization dependent routines, mostly dealing with
24*38104Sbostic  * activation records.
25*38104Sbostic  */
26*38104Sbostic 
27*38104Sbostic #include "defs.h"
28*38104Sbostic #include "runtime.h"
29*38104Sbostic #include "process.h"
30*38104Sbostic #include "machine.h"
31*38104Sbostic #include "events.h"
32*38104Sbostic #include "mappings.h"
33*38104Sbostic #include "symbols.h"
34*38104Sbostic #include "tree.h"
35*38104Sbostic #include "eval.h"
36*38104Sbostic #include "operators.h"
37*38104Sbostic #include "object.h"
38*38104Sbostic #include <sys/param.h>
39*38104Sbostic #include <signal.h>
40*38104Sbostic 
41*38104Sbostic #ifndef public
42*38104Sbostic typedef struct Frame *Frame;
43*38104Sbostic 
44*38104Sbostic #include "machine.h"
45*38104Sbostic #endif
46*38104Sbostic 
47*38104Sbostic #define NSAVEREG 14
48*38104Sbostic 
49*38104Sbostic struct Frame {
50*38104Sbostic     Address save_fp;		/* frame pointer */
51*38104Sbostic     Address save_pc;		/* program counter */
52*38104Sbostic     Word save_reg[NSAVEREG];	/* not necessarily there */
53*38104Sbostic     integer nargwords;		/* computed, not stored */
54*38104Sbostic };
55*38104Sbostic 
56*38104Sbostic private Frame curframe = nil;
57*38104Sbostic private struct Frame curframerec;
58*38104Sbostic private Boolean walkingstack = false;
59*38104Sbostic 
60*38104Sbostic #define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)
61*38104Sbostic 
62*38104Sbostic private boolean inSignalHandler (addr)
63*38104Sbostic Address addr;
64*38104Sbostic {
65*38104Sbostic     Symbol f;
66*38104Sbostic 
67*38104Sbostic #ifdef IRIS
68*38104Sbostic     return false;
69*38104Sbostic #else /* sun */
70*38104Sbostic     f = whatblock(addr);
71*38104Sbostic     return (boolean) (f != nil and streq(symname(f), "_sigtramp"));
72*38104Sbostic #endif
73*38104Sbostic }
74*38104Sbostic 
75*38104Sbostic typedef struct {
76*38104Sbostic     Node callnode;
77*38104Sbostic     Node cmdnode;
78*38104Sbostic     boolean isfunc;
79*38104Sbostic } CallEnv;
80*38104Sbostic 
81*38104Sbostic private CallEnv endproc;
82*38104Sbostic 
83*38104Sbostic /*
84*38104Sbostic  * Set a frame to the current activation record.
85*38104Sbostic  */
86*38104Sbostic 
87*38104Sbostic private getcurframe(frp)
88*38104Sbostic Frame frp;
89*38104Sbostic {
90*38104Sbostic     register int i;
91*38104Sbostic 
92*38104Sbostic     checkref(frp);
93*38104Sbostic     frp->save_fp = reg(FRP);
94*38104Sbostic     frp->save_pc = reg(PROGCTR);
95*38104Sbostic     for (i = 0; i < NSAVEREG; i++) {
96*38104Sbostic 	frp->save_reg[i] = reg(i);
97*38104Sbostic     }
98*38104Sbostic     if (frp->save_fp == nil) {
99*38104Sbostic 	frp->nargwords = 0;
100*38104Sbostic     } else {
101*38104Sbostic 	findnumargs(frp);
102*38104Sbostic     }
103*38104Sbostic }
104*38104Sbostic 
105*38104Sbostic /*
106*38104Sbostic  * Get the saved registers from one frame to another
107*38104Sbostic  * given mask specifying which registers were actually saved.
108*38104Sbostic  */
109*38104Sbostic 
110*38104Sbostic #define bis(b, n) ((b & (1 << (n))) != 0)
111*38104Sbostic 
112*38104Sbostic private getsaveregs (newfrp, frp, mask)
113*38104Sbostic Frame newfrp, frp;
114*38104Sbostic integer mask;
115*38104Sbostic {
116*38104Sbostic     integer i, j;
117*38104Sbostic 
118*38104Sbostic     j = 0;
119*38104Sbostic     for (i = 0; i < NSAVEREG; i++) {
120*38104Sbostic 	if (bis(mask, i)) {
121*38104Sbostic 	    newfrp->save_reg[i] = frp->save_reg[j];
122*38104Sbostic 	    ++j;
123*38104Sbostic 	}
124*38104Sbostic     }
125*38104Sbostic }
126*38104Sbostic 
127*38104Sbostic /*
128*38104Sbostic  * Return a pointer to the next activation record up the stack.
129*38104Sbostic  * Return nil if there is none.
130*38104Sbostic  * Writes over space pointed to by given argument.
131*38104Sbostic  */
132*38104Sbostic 
133*38104Sbostic private Frame nextframe(frp)
134*38104Sbostic Frame frp;
135*38104Sbostic {
136*38104Sbostic     Frame newfrp;
137*38104Sbostic     struct Frame frame;
138*38104Sbostic     integer mask;
139*38104Sbostic     Address prev_frame, callpc, higher_fp, higher_pc;
140*38104Sbostic     static integer ntramp = 0;
141*38104Sbostic 
142*38104Sbostic     newfrp = frp;
143*38104Sbostic     prev_frame = frp->save_fp;
144*38104Sbostic 
145*38104Sbostic /*
146*38104Sbostic  *  The check for interrupt generated frames is taken from adb with only
147*38104Sbostic  *  partial understanding.  If you're in "sub" and on a sigxxx "sigsub"
148*38104Sbostic  *  gets control, then the stack does NOT look like <main, sub, sigsub>.
149*38104Sbostic  *
150*38104Sbostic  *  As best I can make out it looks like:
151*38104Sbostic  *
152*38104Sbostic  *     <main, (machine check exception block + sub), sysframe, sigsub>.
153*38104Sbostic  *
154*38104Sbostic  *  When the signal occurs an exception block and a frame for the routine
155*38104Sbostic  *  in which it occured are pushed on the user stack.  Then another frame
156*38104Sbostic  *  is pushed corresponding to a call from the kernel to sigsub.
157*38104Sbostic  *
158*38104Sbostic  *  The addr in sub at which the exception occured is not in sub.save_pc
159*38104Sbostic  *  but in the machine check exception block.  It is at the magic address
160*38104Sbostic  *  fp + 84.
161*38104Sbostic  *
162*38104Sbostic  *  The current approach ignores the sys_frame (what adb reports as sigtramp)
163*38104Sbostic  *  and takes the pc for sub from the exception block.  This allows the
164*38104Sbostic  *  "where" command to report <main, sub, sigsub>, which seems reasonable.
165*38104Sbostic  */
166*38104Sbostic 
167*38104Sbostic nextf:
168*38104Sbostic     if (prev_frame + sizeof(struct Frame) <= USRSTACK) {
169*38104Sbostic 	dread(&frame, prev_frame, sizeof(struct Frame));
170*38104Sbostic     } else if (USRSTACK - prev_frame > 2 * sizeof(Word)) {
171*38104Sbostic 	dread(&frame, prev_frame, USRSTACK - prev_frame);
172*38104Sbostic     } else {
173*38104Sbostic 	frame.save_fp = nil;
174*38104Sbostic     }
175*38104Sbostic     if (ntramp == 1) {
176*38104Sbostic 	dread(&callpc, prev_frame + 92, sizeof(callpc));
177*38104Sbostic     } else {
178*38104Sbostic 	callpc = frame.save_pc;
179*38104Sbostic     }
180*38104Sbostic     if (frame.save_fp == nil or frame.save_pc == (Address) -1) {
181*38104Sbostic 	newfrp = nil;
182*38104Sbostic     } else {
183*38104Sbostic 	if (inSignalHandler(callpc)) {
184*38104Sbostic #	ifdef sun
185*38104Sbostic 	    Address scp;
186*38104Sbostic 
187*38104Sbostic 	    dread(&scp, prev_frame + 16, sizeof(scp));
188*38104Sbostic 	    dread(&callpc,
189*38104Sbostic 		&(((struct sigcontext *)scp)->sc_pc), sizeof(Word)
190*38104Sbostic 	    );
191*38104Sbostic #	endif /* sun */
192*38104Sbostic 	}
193*38104Sbostic 	frame.save_pc = callpc;
194*38104Sbostic         ntramp = 0;
195*38104Sbostic 	higher_fp = frp->save_fp;
196*38104Sbostic 	higher_pc = frp->save_pc;
197*38104Sbostic 	newfrp->save_fp = frame.save_fp;
198*38104Sbostic 	newfrp->save_pc = frame.save_pc;
199*38104Sbostic 	    findnumargs(newfrp);
200*38104Sbostic 	    findsavedregs(newfrp, higher_fp, higher_pc);
201*38104Sbostic     }
202*38104Sbostic     return newfrp;
203*38104Sbostic }
204*38104Sbostic 
205*38104Sbostic /*
206*38104Sbostic  * Finding the saved registers and number of arguments passed to
207*38104Sbostic  * the current procedure is painful for the 68000.
208*38104Sbostic  *
209*38104Sbostic  * This is a version of the way adb for the 68000 does this.
210*38104Sbostic  */
211*38104Sbostic 
212*38104Sbostic #define HIWORD	0xffff0000
213*38104Sbostic #define LOWORD	0x0000ffff
214*38104Sbostic #define LINKA6	0x4e560000	/* link a6,#x    */
215*38104Sbostic #define ADDLSP	0xdffc0000	/* addl #x,sp    */
216*38104Sbostic #define ADDWSP	0xdefc0000	/* addw #x,sp    */
217*38104Sbostic #define LEASP	0x4fef0000	/* lea	sp@(x),sp*/
218*38104Sbostic #define TSTBSP	0x4a2f0000	/* tstb sp@(x)   */
219*38104Sbostic #define INSMSK	0xfff80000
220*38104Sbostic #define MOVLSP	0x2e800000	/* movl dx,sp@   */
221*38104Sbostic #define MOVLD0	0x20000000	/* movl d0,dx	 */
222*38104Sbostic #define MOVLA0	0x20400000	/* movl d0,ax	 */
223*38104Sbostic #define MVLMSK	0xf1ff0000
224*38104Sbostic #define MOVEML	0x48d70000	/* moveml #x,sp@ */
225*38104Sbostic #define JSR	0x4eb80000	/* jsr x.[WL]    */
226*38104Sbostic #define JSRPC	0x4eba0000	/* jsr PC@( )    */
227*38104Sbostic #define LONGBIT 0x00010000
228*38104Sbostic #define BSR	0x61000000	/* bsr x	 */
229*38104Sbostic #define BYTE3	0x0000ff00
230*38104Sbostic #define LOBYTE	0x000000ff
231*38104Sbostic #define ADQMSK	0xf1ff0000
232*38104Sbostic #define ADDQSP	0x508f0000	/* addql #x,sp   */
233*38104Sbostic #define ADDQWSP	0x504f0000	/* addqw #x,sp   */
234*38104Sbostic 
235*38104Sbostic private int savedregsmask;
236*38104Sbostic private int savedregp;
237*38104Sbostic 
238*38104Sbostic /*
239*38104Sbostic  * Find out how many words of arguments were passed to
240*38104Sbostic  * the current procedure.
241*38104Sbostic  */
242*38104Sbostic 
243*38104Sbostic private findnumargs (newfrp)
244*38104Sbostic Frame newfrp;
245*38104Sbostic {
246*38104Sbostic     integer val;
247*38104Sbostic     integer instruc;
248*38104Sbostic     Address addr;
249*38104Sbostic 
250*38104Sbostic     dread(&addr, newfrp->save_fp + sizeof(Address), sizeof(addr));
251*38104Sbostic     iread(&instruc, addr, sizeof(instruc));
252*38104Sbostic     if ((instruc&MVLMSK) == MOVLA0 or (instruc&MVLMSK) == MOVLD0) {
253*38104Sbostic 	addr += 2;
254*38104Sbostic 	iread(&instruc, addr, sizeof(instruc));
255*38104Sbostic     }
256*38104Sbostic     if ((instruc&ADQMSK) == ADDQSP or (instruc&ADQMSK) == ADDQWSP){
257*38104Sbostic 	val = (instruc >> (16+9)) & 07;
258*38104Sbostic 	if (val == 0) {
259*38104Sbostic 	    val = 8;
260*38104Sbostic 	}
261*38104Sbostic     } else if ((instruc&HIWORD) == ADDLSP){
262*38104Sbostic 	iread(&val, addr + 2, sizeof(val));
263*38104Sbostic     } else if ((instruc&HIWORD) == ADDWSP || (instruc&HIWORD) == LEASP){
264*38104Sbostic 	val = instruc&LOWORD;
265*38104Sbostic     } else {
266*38104Sbostic 	val = 0;
267*38104Sbostic     }
268*38104Sbostic     newfrp->nargwords = val / sizeof(Word);
269*38104Sbostic }
270*38104Sbostic 
271*38104Sbostic /*
272*38104Sbostic  * Get the saved registers for the given Frame.
273*38104Sbostic  */
274*38104Sbostic 
275*38104Sbostic private findsavedregs (newfrp, higher_fp, higher_pc)
276*38104Sbostic Frame newfrp;
277*38104Sbostic register Address higher_fp, higher_pc;
278*38104Sbostic {
279*38104Sbostic     int val, regp, i;
280*38104Sbostic     Address addr;
281*38104Sbostic     Symbol func;
282*38104Sbostic     Address calladdr;
283*38104Sbostic     int instruc;
284*38104Sbostic 
285*38104Sbostic     /*
286*38104Sbostic      * Find the entry point of the current procedure.
287*38104Sbostic      * This is done by finding the procedure for the higher frame's pc
288*38104Sbostic      * and taking its starting address.
289*38104Sbostic      */
290*38104Sbostic     func = whatblock(higher_pc, true);
291*38104Sbostic     calladdr = codeloc(func) - FUNCOFFSET;
292*38104Sbostic 
293*38104Sbostic     /*
294*38104Sbostic      * Look at the entry code for the current procedure
295*38104Sbostic      * to determine which registers were saved, and where they are.
296*38104Sbostic      *
297*38104Sbostic      * First find the size of the activation record.
298*38104Sbostic      */
299*38104Sbostic     addr = calladdr;
300*38104Sbostic     iread(&instruc, addr, sizeof(instruc));
301*38104Sbostic     if ((instruc&HIWORD) == LINKA6) {
302*38104Sbostic 	if ((instruc &= LOWORD) == 0) {
303*38104Sbostic 	    /* look for addl */
304*38104Sbostic 	    addr += 4;
305*38104Sbostic 	    iread(&instruc, addr, sizeof(instruc));
306*38104Sbostic 	    if ((instruc&HIWORD) == ADDLSP) {
307*38104Sbostic 		iread(&instruc, addr + 2, sizeof(instruc));
308*38104Sbostic 		addr += 6;
309*38104Sbostic 	    } else {
310*38104Sbostic 		instruc = 0;
311*38104Sbostic 	    }
312*38104Sbostic 	} else {
313*38104Sbostic 	    /* link offset was non-zero -- sign extend it */
314*38104Sbostic 	    instruc <<= 16;
315*38104Sbostic 	    instruc >>= 16;
316*38104Sbostic 	}
317*38104Sbostic 	/* we now have the negative frame size */
318*38104Sbostic 	regp = higher_fp + instruc;
319*38104Sbostic 	savedregp = regp;
320*38104Sbostic     }
321*38104Sbostic 
322*38104Sbostic     /*
323*38104Sbostic      * Now find which registers were saved.
324*38104Sbostic      * (expecting a probe instruction next)
325*38104Sbostic      */
326*38104Sbostic     iread(&instruc, addr, sizeof(instruc));
327*38104Sbostic     if ((instruc&HIWORD) == TSTBSP) {
328*38104Sbostic 	addr += 4;
329*38104Sbostic 	iread(&instruc, addr, sizeof(instruc));
330*38104Sbostic     }
331*38104Sbostic     /*
332*38104Sbostic      * expect either a moveml or a movl next
333*38104Sbostic      */
334*38104Sbostic     if ((instruc&INSMSK) == MOVLSP){
335*38104Sbostic 	/*
336*38104Sbostic 	 * Only one register saved.
337*38104Sbostic 	 */
338*38104Sbostic 	i = (instruc>>16) & 07;
339*38104Sbostic 	dread(&(newfrp->save_reg[i]), regp, sizeof(Word));
340*38104Sbostic 	savedregsmask = 1 << i;
341*38104Sbostic     } else if ((instruc&HIWORD) == MOVEML) {
342*38104Sbostic 	/*
343*38104Sbostic 	 * Saving multiple registers or unoptimized code
344*38104Sbostic 	 */
345*38104Sbostic 	val = instruc & LOWORD;
346*38104Sbostic 	savedregsmask = val;
347*38104Sbostic 	i = 0;
348*38104Sbostic 	while (val != 0) {
349*38104Sbostic 	    if (val&1) {
350*38104Sbostic 		dread(&(newfrp->save_reg[i]), regp, sizeof(Word));
351*38104Sbostic 		regp += sizeof(Word);
352*38104Sbostic 	    }
353*38104Sbostic 	    val >>= 1;
354*38104Sbostic 	    ++i;
355*38104Sbostic 	}
356*38104Sbostic     } else {
357*38104Sbostic 	savedregsmask = 0;
358*38104Sbostic     }
359*38104Sbostic }
360*38104Sbostic 
361*38104Sbostic /*
362*38104Sbostic  * Get the current frame information in the given Frame and store the
363*38104Sbostic  * associated function in the given value-result parameter.
364*38104Sbostic  */
365*38104Sbostic 
366*38104Sbostic private getcurfunc (frp, fp)
367*38104Sbostic Frame frp;
368*38104Sbostic Symbol *fp;
369*38104Sbostic {
370*38104Sbostic     getcurframe(frp);
371*38104Sbostic     *fp = whatblock(frp->save_pc);
372*38104Sbostic }
373*38104Sbostic 
374*38104Sbostic /*
375*38104Sbostic  * Return the frame associated with the next function up the call stack, or
376*38104Sbostic  * nil if there is none.  The function is returned in a value-result parameter.
377*38104Sbostic  * For "inline" functions the statically outer function and same frame
378*38104Sbostic  * are returned.
379*38104Sbostic  */
380*38104Sbostic 
381*38104Sbostic public Frame nextfunc (frp, fp)
382*38104Sbostic Frame frp;
383*38104Sbostic Symbol *fp;
384*38104Sbostic {
385*38104Sbostic     Symbol t;
386*38104Sbostic     Frame nfrp;
387*38104Sbostic 
388*38104Sbostic     t = *fp;
389*38104Sbostic     checkref(t);
390*38104Sbostic     if (isinline(t)) {
391*38104Sbostic 	t = container(t);
392*38104Sbostic 	nfrp = frp;
393*38104Sbostic     } else {
394*38104Sbostic 	nfrp = nextframe(frp);
395*38104Sbostic 	if (nfrp == nil) {
396*38104Sbostic 	    t = nil;
397*38104Sbostic 	} else {
398*38104Sbostic 	    t = whatblock(nfrp->save_pc);
399*38104Sbostic 	}
400*38104Sbostic     }
401*38104Sbostic     *fp = t;
402*38104Sbostic     return nfrp;
403*38104Sbostic }
404*38104Sbostic 
405*38104Sbostic /*
406*38104Sbostic  * Return the frame associated with the given function.
407*38104Sbostic  * If the function is nil, return the most recently activated frame.
408*38104Sbostic  *
409*38104Sbostic  * Static allocation for the frame.
410*38104Sbostic  */
411*38104Sbostic 
412*38104Sbostic public Frame findframe(f)
413*38104Sbostic Symbol f;
414*38104Sbostic {
415*38104Sbostic     Frame frp;
416*38104Sbostic     static struct Frame frame;
417*38104Sbostic     Symbol p;
418*38104Sbostic     Boolean done;
419*38104Sbostic 
420*38104Sbostic     frp = &frame;
421*38104Sbostic     getcurframe(frp);
422*38104Sbostic     if (f != nil) {
423*38104Sbostic 	if (f == curfunc and curframe != nil) {
424*38104Sbostic 	    *frp = *curframe;
425*38104Sbostic 	} else {
426*38104Sbostic 	    done = false;
427*38104Sbostic 	    p = whatblock(frp->save_pc);
428*38104Sbostic 	    do {
429*38104Sbostic 		if (p == f) {
430*38104Sbostic 		    done = true;
431*38104Sbostic 		} else if (p == program) {
432*38104Sbostic 		    done = true;
433*38104Sbostic 		    frp = nil;
434*38104Sbostic 		} else {
435*38104Sbostic 		    frp = nextfunc(frp, &p);
436*38104Sbostic 		    if (frp == nil) {
437*38104Sbostic 			done = true;
438*38104Sbostic 		    }
439*38104Sbostic 		}
440*38104Sbostic 	    } while (not done);
441*38104Sbostic 	}
442*38104Sbostic     }
443*38104Sbostic     return frp;
444*38104Sbostic }
445*38104Sbostic 
446*38104Sbostic /*
447*38104Sbostic  * Set the registers according to the given frame pointer.
448*38104Sbostic  */
449*38104Sbostic 
450*38104Sbostic public getnewregs (addr)
451*38104Sbostic Address addr;
452*38104Sbostic {
453*38104Sbostic     struct Frame frame;
454*38104Sbostic     integer i, j, mask;
455*38104Sbostic 
456*38104Sbostic     dread(&frame, addr, sizeof(frame));
457*38104Sbostic     setreg(FRP, frame.save_fp);
458*38104Sbostic     setreg(PROGCTR, frame.save_pc);
459*38104Sbostic     pc = frame.save_pc;
460*38104Sbostic     setcurfunc(whatblock(pc));
461*38104Sbostic }
462*38104Sbostic 
463*38104Sbostic /*
464*38104Sbostic  * Find the return address of the current procedure/function.
465*38104Sbostic  */
466*38104Sbostic 
467*38104Sbostic public Address return_addr()
468*38104Sbostic {
469*38104Sbostic     Frame frp;
470*38104Sbostic     Address addr;
471*38104Sbostic     struct Frame frame;
472*38104Sbostic 
473*38104Sbostic     frp = &frame;
474*38104Sbostic     getcurframe(frp);
475*38104Sbostic     frp = nextframe(frp);
476*38104Sbostic     if (frp == nil) {
477*38104Sbostic 	addr = 0;
478*38104Sbostic     } else {
479*38104Sbostic 	addr = frp->save_pc;
480*38104Sbostic     }
481*38104Sbostic     return addr;
482*38104Sbostic }
483*38104Sbostic 
484*38104Sbostic /*
485*38104Sbostic  * Push the value associated with the current function.
486*38104Sbostic  */
487*38104Sbostic 
488*38104Sbostic public pushretval(len, isindirect)
489*38104Sbostic integer len;
490*38104Sbostic boolean isindirect;
491*38104Sbostic {
492*38104Sbostic     Word r0;
493*38104Sbostic 
494*38104Sbostic     r0 = reg(0);
495*38104Sbostic     if (isindirect) {
496*38104Sbostic 	rpush((Address) r0, len);
497*38104Sbostic     } else {
498*38104Sbostic 	switch (len) {
499*38104Sbostic 	    case sizeof(char):
500*38104Sbostic 		push(char, r0);
501*38104Sbostic 		break;
502*38104Sbostic 
503*38104Sbostic 	    case sizeof(short):
504*38104Sbostic 		push(short, r0);
505*38104Sbostic 		break;
506*38104Sbostic 
507*38104Sbostic 	    default:
508*38104Sbostic 		if (len == sizeof(Word)) {
509*38104Sbostic 		    push(Word, r0);
510*38104Sbostic 		} else if (len == 2*sizeof(Word)) {
511*38104Sbostic 		    push(Word, r0);
512*38104Sbostic 		    push(Word, reg(1));
513*38104Sbostic 		} else {
514*38104Sbostic 		    error("[internal error: bad size %d in pushretval]", len);
515*38104Sbostic 		}
516*38104Sbostic 		break;
517*38104Sbostic 	}
518*38104Sbostic     }
519*38104Sbostic }
520*38104Sbostic 
521*38104Sbostic /*
522*38104Sbostic  * Return the base address for locals in the given frame.
523*38104Sbostic  */
524*38104Sbostic 
525*38104Sbostic public Address locals_base(frp)
526*38104Sbostic Frame frp;
527*38104Sbostic {
528*38104Sbostic     return (frp == nil) ? reg(FRP) : frp->save_fp;
529*38104Sbostic }
530*38104Sbostic 
531*38104Sbostic /*
532*38104Sbostic  * Return the base address for arguments in the given frame.
533*38104Sbostic  */
534*38104Sbostic 
535*38104Sbostic public Address args_base(frp)
536*38104Sbostic Frame frp;
537*38104Sbostic {
538*38104Sbostic     return (frp == nil) ? reg(FRP) : frp->save_fp;
539*38104Sbostic }
540*38104Sbostic 
541*38104Sbostic /*
542*38104Sbostic  * Return saved register n from the given frame.
543*38104Sbostic  */
544*38104Sbostic 
545*38104Sbostic public Word savereg(n, frp)
546*38104Sbostic integer n;
547*38104Sbostic Frame frp;
548*38104Sbostic {
549*38104Sbostic     Word w;
550*38104Sbostic 
551*38104Sbostic     if (frp == nil) {
552*38104Sbostic 	w = reg(n);
553*38104Sbostic     } else {
554*38104Sbostic 	switch (n) {
555*38104Sbostic 	    case FRP:
556*38104Sbostic 		w = frp->save_fp;
557*38104Sbostic 		break;
558*38104Sbostic 
559*38104Sbostic 	    case STKP:
560*38104Sbostic 		w = reg(STKP);
561*38104Sbostic 		break;
562*38104Sbostic 
563*38104Sbostic 	    case PROGCTR:
564*38104Sbostic 		w = frp->save_pc;
565*38104Sbostic 		break;
566*38104Sbostic 
567*38104Sbostic 	    default:
568*38104Sbostic 		assert(n >= 0 and n < NSAVEREG);
569*38104Sbostic 		w = frp->save_reg[n];
570*38104Sbostic 		break;
571*38104Sbostic 	}
572*38104Sbostic     }
573*38104Sbostic     return w;
574*38104Sbostic }
575*38104Sbostic 
576*38104Sbostic /*
577*38104Sbostic  * Return the nth argument to the current procedure.
578*38104Sbostic  */
579*38104Sbostic 
580*38104Sbostic public Word argn(n, frp)
581*38104Sbostic integer n;
582*38104Sbostic Frame frp;
583*38104Sbostic {
584*38104Sbostic     Address argaddr;
585*38104Sbostic     Word w;
586*38104Sbostic 
587*38104Sbostic     argaddr = args_base(frp) + 4 + (n * sizeof(Word));
588*38104Sbostic     dread(&w, argaddr, sizeof(w));
589*38104Sbostic     return w;
590*38104Sbostic }
591*38104Sbostic 
592*38104Sbostic /*
593*38104Sbostic  * Return the number of words of arguments passed to the procedure
594*38104Sbostic  * associated with the given frame (it's a macro for the VAX).
595*38104Sbostic  */
596*38104Sbostic 
597*38104Sbostic public integer nargspassed (frp)
598*38104Sbostic Frame frp;
599*38104Sbostic {
600*38104Sbostic     integer n;
601*38104Sbostic     struct Frame frame;
602*38104Sbostic 
603*38104Sbostic     if (frp == nil) {
604*38104Sbostic 	getcurframe(&frame);
605*38104Sbostic 	n = frame.nargwords;
606*38104Sbostic     } else {
607*38104Sbostic 	n = frp->nargwords;
608*38104Sbostic     }
609*38104Sbostic     return n;
610*38104Sbostic }
611*38104Sbostic 
612*38104Sbostic /*
613*38104Sbostic  * Print a list of currently active blocks starting with most recent.
614*38104Sbostic  */
615*38104Sbostic 
616*38104Sbostic public wherecmd()
617*38104Sbostic {
618*38104Sbostic     walkstack(false);
619*38104Sbostic }
620*38104Sbostic 
621*38104Sbostic /*
622*38104Sbostic  * Print the variables in the given frame or the current one if nil.
623*38104Sbostic  */
624*38104Sbostic 
625*38104Sbostic public dump (func)
626*38104Sbostic Symbol func;
627*38104Sbostic {
628*38104Sbostic     Symbol f;
629*38104Sbostic     Frame frp;
630*38104Sbostic 
631*38104Sbostic     if (func == nil) {
632*38104Sbostic 	f = curfunc;
633*38104Sbostic 	if (curframe != nil) {
634*38104Sbostic 	    frp = curframe;
635*38104Sbostic 	} else {
636*38104Sbostic 	    frp = findframe(f);
637*38104Sbostic 	}
638*38104Sbostic     } else {
639*38104Sbostic 	f = func;
640*38104Sbostic 	frp = findframe(f);
641*38104Sbostic     }
642*38104Sbostic     showaggrs = true;
643*38104Sbostic     printcallinfo(f, frp);
644*38104Sbostic     dumpvars(f, frp);
645*38104Sbostic }
646*38104Sbostic 
647*38104Sbostic /*
648*38104Sbostic  * Dump all values.
649*38104Sbostic  */
650*38104Sbostic 
651*38104Sbostic public dumpall ()
652*38104Sbostic {
653*38104Sbostic     walkstack(true);
654*38104Sbostic }
655*38104Sbostic 
656*38104Sbostic /*
657*38104Sbostic  * Walk the stack of active procedures printing information
658*38104Sbostic  * about each active procedure.
659*38104Sbostic  */
660*38104Sbostic 
661*38104Sbostic private walkstack(dumpvariables)
662*38104Sbostic Boolean dumpvariables;
663*38104Sbostic {
664*38104Sbostic     Frame frp;
665*38104Sbostic     boolean save;
666*38104Sbostic     Symbol f;
667*38104Sbostic     struct Frame frame;
668*38104Sbostic 
669*38104Sbostic     if (notstarted(process) or isfinished(process)) {
670*38104Sbostic 	error("program is not active");
671*38104Sbostic     } else {
672*38104Sbostic 	save = walkingstack;
673*38104Sbostic 	walkingstack = true;
674*38104Sbostic 	showaggrs = dumpvariables;
675*38104Sbostic 	frp = &frame;
676*38104Sbostic 	getcurfunc(frp, &f);
677*38104Sbostic 	for (;;) {
678*38104Sbostic 	    printcallinfo(f, frp);
679*38104Sbostic 	    if (dumpvariables) {
680*38104Sbostic 		dumpvars(f, frp);
681*38104Sbostic 		putchar('\n');
682*38104Sbostic 	    }
683*38104Sbostic 	    frp = nextfunc(frp, &f);
684*38104Sbostic 	    if (frp == nil or f == program) {
685*38104Sbostic 		break;
686*38104Sbostic 	    }
687*38104Sbostic 	}
688*38104Sbostic 	if (dumpvariables) {
689*38104Sbostic 	    printf("in \"%s\":\n", symname(program));
690*38104Sbostic 	    dumpvars(program, nil);
691*38104Sbostic 	    putchar('\n');
692*38104Sbostic 	}
693*38104Sbostic 	walkingstack = save;
694*38104Sbostic     }
695*38104Sbostic }
696*38104Sbostic 
697*38104Sbostic /*
698*38104Sbostic  * Print out the information about a call, i.e.,
699*38104Sbostic  * routine name, parameter values, and source location.
700*38104Sbostic  */
701*38104Sbostic 
702*38104Sbostic private printcallinfo (f, frp)
703*38104Sbostic Symbol f;
704*38104Sbostic Frame frp;
705*38104Sbostic {
706*38104Sbostic     Lineno line;
707*38104Sbostic     Address savepc;
708*38104Sbostic 
709*38104Sbostic     savepc = frp->save_pc;
710*38104Sbostic     if (frp->save_fp != reg(FRP)) {
711*38104Sbostic 	savepc -= 1;
712*38104Sbostic     }
713*38104Sbostic     printname(stdout, f);
714*38104Sbostic     if (not isinline(f)) {
715*38104Sbostic 	printparams(f, frp);
716*38104Sbostic     }
717*38104Sbostic     line = srcline(savepc);
718*38104Sbostic     if (line != 0) {
719*38104Sbostic 	printf(", line %d", line);
720*38104Sbostic 	printf(" in \"%s\"\n", srcfilename(savepc));
721*38104Sbostic     } else {
722*38104Sbostic 	printf(" at 0x%x\n", savepc);
723*38104Sbostic     }
724*38104Sbostic }
725*38104Sbostic 
726*38104Sbostic /*
727*38104Sbostic  * Set the current function to the given symbol.
728*38104Sbostic  * We must adjust "curframe" so that subsequent operations are
729*38104Sbostic  * not confused; for simplicity we simply clear it.
730*38104Sbostic  */
731*38104Sbostic 
732*38104Sbostic public setcurfunc (f)
733*38104Sbostic Symbol f;
734*38104Sbostic {
735*38104Sbostic     curfunc = f;
736*38104Sbostic     curframe = nil;
737*38104Sbostic }
738*38104Sbostic 
739*38104Sbostic /*
740*38104Sbostic  * Return the frame for the current function.
741*38104Sbostic  * The space for the frame is allocated statically.
742*38104Sbostic  */
743*38104Sbostic 
744*38104Sbostic public Frame curfuncframe ()
745*38104Sbostic {
746*38104Sbostic     static struct Frame frame;
747*38104Sbostic     Frame frp;
748*38104Sbostic 
749*38104Sbostic     if (curframe == nil) {
750*38104Sbostic 	frp = findframe(curfunc);
751*38104Sbostic 	curframe = &curframerec;
752*38104Sbostic 	*curframe = *frp;
753*38104Sbostic     } else {
754*38104Sbostic 	frp = &frame;
755*38104Sbostic 	*frp = *curframe;
756*38104Sbostic     }
757*38104Sbostic     return frp;
758*38104Sbostic }
759*38104Sbostic 
760*38104Sbostic /*
761*38104Sbostic  * Set curfunc to be N up/down the stack from its current value.
762*38104Sbostic  */
763*38104Sbostic 
764*38104Sbostic public up (n)
765*38104Sbostic integer n;
766*38104Sbostic {
767*38104Sbostic     integer i;
768*38104Sbostic     Symbol f;
769*38104Sbostic     Frame frp;
770*38104Sbostic     boolean done;
771*38104Sbostic 
772*38104Sbostic     if (not isactive(program)) {
773*38104Sbostic 	error("program is not active");
774*38104Sbostic     } else if (curfunc == nil) {
775*38104Sbostic 	error("no current function");
776*38104Sbostic     } else {
777*38104Sbostic 	i = 0;
778*38104Sbostic 	f = curfunc;
779*38104Sbostic 	frp = curfuncframe();
780*38104Sbostic 	done = false;
781*38104Sbostic 	do {
782*38104Sbostic 	    if (frp == nil) {
783*38104Sbostic 		done = true;
784*38104Sbostic 		error("not that many levels");
785*38104Sbostic 	    } else if (i >= n) {
786*38104Sbostic 		done = true;
787*38104Sbostic 		curfunc = f;
788*38104Sbostic 		curframe = &curframerec;
789*38104Sbostic 		*curframe = *frp;
790*38104Sbostic 		showaggrs = false;
791*38104Sbostic 		printcallinfo(curfunc, curframe);
792*38104Sbostic 	    } else if (f == program) {
793*38104Sbostic 		done = true;
794*38104Sbostic 		error("not that many levels");
795*38104Sbostic 	    } else {
796*38104Sbostic 		frp = nextfunc(frp, &f);
797*38104Sbostic 	    }
798*38104Sbostic 	    ++i;
799*38104Sbostic 	} while (not done);
800*38104Sbostic     }
801*38104Sbostic }
802*38104Sbostic 
803*38104Sbostic public down (n)
804*38104Sbostic integer n;
805*38104Sbostic {
806*38104Sbostic     integer i, depth;
807*38104Sbostic     Frame frp, curfrp;
808*38104Sbostic     Symbol f;
809*38104Sbostic     struct Frame frame;
810*38104Sbostic 
811*38104Sbostic     if (not isactive(program)) {
812*38104Sbostic 	error("program is not active");
813*38104Sbostic     } else if (curfunc == nil) {
814*38104Sbostic 	error("no current function");
815*38104Sbostic     } else {
816*38104Sbostic 	depth = 0;
817*38104Sbostic 	frp = &frame;
818*38104Sbostic 	getcurfunc(frp, &f);
819*38104Sbostic 	if (curframe == nil) {
820*38104Sbostic 	    curfrp = findframe(curfunc);
821*38104Sbostic 	    curframe = &curframerec;
822*38104Sbostic 	    *curframe = *curfrp;
823*38104Sbostic 	}
824*38104Sbostic 	while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) {
825*38104Sbostic 	    frp = nextfunc(frp, &f);
826*38104Sbostic 	    ++depth;
827*38104Sbostic 	}
828*38104Sbostic 	if (f == nil or n > depth) {
829*38104Sbostic 	    error("not that many levels");
830*38104Sbostic 	} else {
831*38104Sbostic 	    depth -= n;
832*38104Sbostic 	    frp = &frame;
833*38104Sbostic 	    getcurfunc(frp, &f);
834*38104Sbostic 	    for (i = 0; i < depth; i++) {
835*38104Sbostic 		frp = nextfunc(frp, &f);
836*38104Sbostic 		assert(frp != nil);
837*38104Sbostic 	    }
838*38104Sbostic 	    curfunc = f;
839*38104Sbostic 	    *curframe = *frp;
840*38104Sbostic 	    showaggrs = false;
841*38104Sbostic 	    printcallinfo(curfunc, curframe);
842*38104Sbostic 	}
843*38104Sbostic     }
844*38104Sbostic }
845*38104Sbostic 
846*38104Sbostic /*
847*38104Sbostic  * Find the entry point of a procedure or function.
848*38104Sbostic  */
849*38104Sbostic 
850*38104Sbostic public findbeginning (f)
851*38104Sbostic Symbol f;
852*38104Sbostic {
853*38104Sbostic     if (isinternal(f)) {
854*38104Sbostic 	f->symvalue.funcv.beginaddr += 18;	/* VAX only */
855*38104Sbostic     } else {
856*38104Sbostic 	/* on 68000's don't add for beginning of program */
857*38104Sbostic 	if (f->symvalue.funcv.beginaddr != CODESTART) {
858*38104Sbostic 	    f->symvalue.funcv.beginaddr += FUNCOFFSET;
859*38104Sbostic 	}
860*38104Sbostic     }
861*38104Sbostic }
862*38104Sbostic 
863*38104Sbostic /*
864*38104Sbostic  * Return the address corresponding to the first line in a function.
865*38104Sbostic  */
866*38104Sbostic 
867*38104Sbostic public Address firstline(f)
868*38104Sbostic Symbol f;
869*38104Sbostic {
870*38104Sbostic     Address addr;
871*38104Sbostic 
872*38104Sbostic     addr = codeloc(f);
873*38104Sbostic     while (linelookup(addr) == 0 and addr < objsize) {
874*38104Sbostic 	++addr;
875*38104Sbostic     }
876*38104Sbostic     if (addr == objsize) {
877*38104Sbostic 	addr = -1;
878*38104Sbostic     }
879*38104Sbostic     return addr;
880*38104Sbostic }
881*38104Sbostic 
882*38104Sbostic /*
883*38104Sbostic  * Catcher drops strike three ...
884*38104Sbostic  */
885*38104Sbostic 
886*38104Sbostic public runtofirst()
887*38104Sbostic {
888*38104Sbostic     Address addr, endaddr;
889*38104Sbostic 
890*38104Sbostic     addr = pc;
891*38104Sbostic     endaddr = objsize + CODESTART;
892*38104Sbostic     while (linelookup(addr) == 0 and addr < endaddr) {
893*38104Sbostic 	++addr;
894*38104Sbostic     }
895*38104Sbostic     if (addr < endaddr) {
896*38104Sbostic 	stepto(addr);
897*38104Sbostic     }
898*38104Sbostic }
899*38104Sbostic 
900*38104Sbostic /*
901*38104Sbostic  * Return the address corresponding to the end of the program.
902*38104Sbostic  *
903*38104Sbostic  * We look for the entry to "exit".
904*38104Sbostic  */
905*38104Sbostic 
906*38104Sbostic public Address lastaddr()
907*38104Sbostic {
908*38104Sbostic     Symbol s;
909*38104Sbostic 
910*38104Sbostic     s = lookup(identname("exit", true));
911*38104Sbostic     if (s == nil) {
912*38104Sbostic 	panic("can't find exit");
913*38104Sbostic     }
914*38104Sbostic     return codeloc(s);
915*38104Sbostic }
916*38104Sbostic 
917*38104Sbostic /*
918*38104Sbostic  * Decide if the given function is currently active.
919*38104Sbostic  *
920*38104Sbostic  * We avoid calls to "findframe" during a stack trace for efficiency.
921*38104Sbostic  * Presumably information evaluated while walking the stack is active.
922*38104Sbostic  */
923*38104Sbostic 
924*38104Sbostic public Boolean isactive (f)
925*38104Sbostic Symbol f;
926*38104Sbostic {
927*38104Sbostic     Boolean b;
928*38104Sbostic 
929*38104Sbostic     if (isfinished(process)) {
930*38104Sbostic 	b = false;
931*38104Sbostic     } else {
932*38104Sbostic 	if (walkingstack or f == program or f == nil or
933*38104Sbostic 	  (ismodule(f) and isactive(container(f)))) {
934*38104Sbostic 	    b = true;
935*38104Sbostic 	} else {
936*38104Sbostic 	    b = (Boolean) (findframe(f) != nil);
937*38104Sbostic 	}
938*38104Sbostic     }
939*38104Sbostic     return b;
940*38104Sbostic }
941*38104Sbostic 
942*38104Sbostic /*
943*38104Sbostic  * Evaluate a call to a procedure.
944*38104Sbostic  */
945*38104Sbostic 
946*38104Sbostic public callproc(exprnode, isfunc)
947*38104Sbostic Node exprnode;
948*38104Sbostic boolean isfunc;
949*38104Sbostic {
950*38104Sbostic     Node procnode, arglist;
951*38104Sbostic     Symbol proc;
952*38104Sbostic     integer argc;
953*38104Sbostic 
954*38104Sbostic     procnode = exprnode->value.arg[0];
955*38104Sbostic     arglist = exprnode->value.arg[1];
956*38104Sbostic     if (procnode->op != O_SYM) {
957*38104Sbostic 	beginerrmsg();
958*38104Sbostic 	fprintf(stderr, "can't call \"");
959*38104Sbostic 	prtree(stderr, procnode);
960*38104Sbostic 	fprintf(stderr, "\"");
961*38104Sbostic 	enderrmsg();
962*38104Sbostic     }
963*38104Sbostic     assert(procnode->op == O_SYM);
964*38104Sbostic     proc = procnode->value.sym;
965*38104Sbostic     if (not isblock(proc)) {
966*38104Sbostic 	error("\"%s\" is not a procedure or function", symname(proc));
967*38104Sbostic     }
968*38104Sbostic     endproc.isfunc = isfunc;
969*38104Sbostic     endproc.callnode = exprnode;
970*38104Sbostic     endproc.cmdnode = topnode;
971*38104Sbostic     pushenv();
972*38104Sbostic     pc = codeloc(proc);
973*38104Sbostic     argc = pushargs(proc, arglist);
974*38104Sbostic     setreg(FRP, 1);	/* have to ensure it's non-zero for return_addr() */
975*38104Sbostic     beginproc(proc, argc);
976*38104Sbostic     event_once(
977*38104Sbostic 	build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
978*38104Sbostic 	buildcmdlist(build(O_PROCRTN, proc))
979*38104Sbostic     );
980*38104Sbostic     isstopped = false;
981*38104Sbostic     if (not bpact()) {
982*38104Sbostic 	isstopped = true;
983*38104Sbostic 	cont(0);
984*38104Sbostic     }
985*38104Sbostic     /*
986*38104Sbostic      * bpact() won't return true, it will call printstatus() and go back
987*38104Sbostic      * to command input if a breakpoint is found.
988*38104Sbostic      */
989*38104Sbostic     /* NOTREACHED */
990*38104Sbostic }
991*38104Sbostic 
992*38104Sbostic /*
993*38104Sbostic  * Push the arguments on the process' stack.  We do this by first
994*38104Sbostic  * evaluating them on the "eval" stack, then copying into the process'
995*38104Sbostic  * space.
996*38104Sbostic  */
997*38104Sbostic 
998*38104Sbostic private integer pushargs(proc, arglist)
999*38104Sbostic Symbol proc;
1000*38104Sbostic Node arglist;
1001*38104Sbostic {
1002*38104Sbostic     Stack *savesp;
1003*38104Sbostic     int argc, args_size;
1004*38104Sbostic 
1005*38104Sbostic     savesp = sp;
1006*38104Sbostic     if (varIsSet("$unsafecall")) {
1007*38104Sbostic 	argc = unsafe_evalargs(proc, arglist);
1008*38104Sbostic     } else {
1009*38104Sbostic 	argc = evalargs(proc, arglist);
1010*38104Sbostic     }
1011*38104Sbostic     args_size = sp - savesp;
1012*38104Sbostic     setreg(STKP, reg(STKP) - args_size);
1013*38104Sbostic     dwrite(savesp, reg(STKP), args_size);
1014*38104Sbostic     sp = savesp;
1015*38104Sbostic     return argc;
1016*38104Sbostic }
1017*38104Sbostic 
1018*38104Sbostic /*
1019*38104Sbostic  * Check to see if an expression is correct for a given parameter.
1020*38104Sbostic  * If the given parameter is false, don't worry about type inconsistencies.
1021*38104Sbostic  *
1022*38104Sbostic  * Return whether or not it is ok.
1023*38104Sbostic  */
1024*38104Sbostic 
1025*38104Sbostic private boolean chkparam (actual, formal, chk)
1026*38104Sbostic Node actual;
1027*38104Sbostic Symbol formal;
1028*38104Sbostic boolean chk;
1029*38104Sbostic {
1030*38104Sbostic     boolean b;
1031*38104Sbostic 
1032*38104Sbostic     b = true;
1033*38104Sbostic     if (chk) {
1034*38104Sbostic 	if (formal == nil) {
1035*38104Sbostic 	    beginerrmsg();
1036*38104Sbostic 	    fprintf(stderr, "too many parameters");
1037*38104Sbostic 	    b = false;
1038*38104Sbostic 	} else if (not compatible(formal->type, actual->nodetype)) {
1039*38104Sbostic 	    beginerrmsg();
1040*38104Sbostic 	    fprintf(stderr, "type mismatch for %s", symname(formal));
1041*38104Sbostic 	    b = false;
1042*38104Sbostic 	}
1043*38104Sbostic     }
1044*38104Sbostic     if (b and formal != nil and
1045*38104Sbostic 	isvarparam(formal) and not isopenarray(formal->type) and
1046*38104Sbostic 	not (
1047*38104Sbostic 	    actual->op == O_RVAL or actual->nodetype == t_addr or
1048*38104Sbostic 	    (
1049*38104Sbostic 		actual->op == O_TYPERENAME and
1050*38104Sbostic 		(
1051*38104Sbostic 		    actual->value.arg[0]->op == O_RVAL or
1052*38104Sbostic 		    actual->value.arg[0]->nodetype == t_addr
1053*38104Sbostic 		)
1054*38104Sbostic 	    )
1055*38104Sbostic 	)
1056*38104Sbostic     ) {
1057*38104Sbostic 	beginerrmsg();
1058*38104Sbostic 	fprintf(stderr, "expected variable, found \"");
1059*38104Sbostic 	prtree(stderr, actual);
1060*38104Sbostic 	fprintf(stderr, "\"");
1061*38104Sbostic 	b = false;
1062*38104Sbostic     }
1063*38104Sbostic     return b;
1064*38104Sbostic }
1065*38104Sbostic 
1066*38104Sbostic /*
1067*38104Sbostic  * Pass an expression to a particular parameter.
1068*38104Sbostic  *
1069*38104Sbostic  * Normally we pass either the address or value, but in some cases
1070*38104Sbostic  * (such as C strings) we want to copy the value onto the stack and
1071*38104Sbostic  * pass its address.
1072*38104Sbostic  *
1073*38104Sbostic  * Another special case raised by strings is the possibility that
1074*38104Sbostic  * the actual parameter will be larger than the formal, even with
1075*38104Sbostic  * appropriate type-checking.  This occurs because we assume during
1076*38104Sbostic  * evaluation that strings are null-terminated, whereas some languages,
1077*38104Sbostic  * notably Pascal, do not work under that assumption.
1078*38104Sbostic  */
1079*38104Sbostic 
1080*38104Sbostic private passparam (actual, formal)
1081*38104Sbostic Node actual;
1082*38104Sbostic Symbol formal;
1083*38104Sbostic {
1084*38104Sbostic     boolean b;
1085*38104Sbostic     Address addr;
1086*38104Sbostic     Stack *savesp;
1087*38104Sbostic     integer actsize, formsize;
1088*38104Sbostic 
1089*38104Sbostic     if (formal != nil and isvarparam(formal) and
1090*38104Sbostic 	(not isopenarray(formal->type))
1091*38104Sbostic     ) {
1092*38104Sbostic 	addr = lval(actual->value.arg[0]);
1093*38104Sbostic 	push(Address, addr);
1094*38104Sbostic     } else if (passaddr(formal, actual->nodetype)) {
1095*38104Sbostic 	savesp = sp;
1096*38104Sbostic 	eval(actual);
1097*38104Sbostic 	actsize = sp - savesp;
1098*38104Sbostic 	setreg(STKP,
1099*38104Sbostic 	    reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1))
1100*38104Sbostic 	);
1101*38104Sbostic 	dwrite(savesp, reg(STKP), actsize);
1102*38104Sbostic 	sp = savesp;
1103*38104Sbostic 	push(Address, reg(STKP));
1104*38104Sbostic 	if (formal != nil and isopenarray(formal->type)) {
1105*38104Sbostic 	    push(integer, actsize div size(formal->type->type));
1106*38104Sbostic 	}
1107*38104Sbostic     } else if (formal != nil) {
1108*38104Sbostic 	formsize = size(formal);
1109*38104Sbostic 	savesp = sp;
1110*38104Sbostic 	eval(actual);
1111*38104Sbostic 	actsize = sp - savesp;
1112*38104Sbostic 	if (actsize > formsize) {
1113*38104Sbostic 	    sp -= (actsize - formsize);
1114*38104Sbostic 	}
1115*38104Sbostic     } else {
1116*38104Sbostic 	eval(actual);
1117*38104Sbostic     }
1118*38104Sbostic }
1119*38104Sbostic 
1120*38104Sbostic /*
1121*38104Sbostic  * Evaluate an argument list left-to-right.
1122*38104Sbostic  */
1123*38104Sbostic 
1124*38104Sbostic private integer evalargs(proc, arglist)
1125*38104Sbostic Symbol proc;
1126*38104Sbostic Node arglist;
1127*38104Sbostic {
1128*38104Sbostic     Node p, actual;
1129*38104Sbostic     Symbol formal;
1130*38104Sbostic     Stack *savesp;
1131*38104Sbostic     integer count;
1132*38104Sbostic     boolean chk;
1133*38104Sbostic 
1134*38104Sbostic     savesp = sp;
1135*38104Sbostic     count = 0;
1136*38104Sbostic     formal = proc->chain;
1137*38104Sbostic     chk = (boolean) (not nosource(proc));
1138*38104Sbostic     for (p = arglist; p != nil; p = p->value.arg[1]) {
1139*38104Sbostic 	assert(p->op == O_COMMA);
1140*38104Sbostic 	actual = p->value.arg[0];
1141*38104Sbostic 	if (not chkparam(actual, formal, chk)) {
1142*38104Sbostic 	    fprintf(stderr, " in call to %s", symname(proc));
1143*38104Sbostic 	    sp = savesp;
1144*38104Sbostic 	    enderrmsg();
1145*38104Sbostic 	}
1146*38104Sbostic 	passparam(actual, formal);
1147*38104Sbostic 	if (formal != nil) {
1148*38104Sbostic 	    formal = formal->chain;
1149*38104Sbostic 	}
1150*38104Sbostic 	++count;
1151*38104Sbostic     }
1152*38104Sbostic     if (chk) {
1153*38104Sbostic 	if (formal != nil) {
1154*38104Sbostic 	    sp = savesp;
1155*38104Sbostic 	    error("not enough parameters to %s", symname(proc));
1156*38104Sbostic 	}
1157*38104Sbostic     }
1158*38104Sbostic     return count;
1159*38104Sbostic }
1160*38104Sbostic 
1161*38104Sbostic /*
1162*38104Sbostic  * Evaluate an argument list without any type checking.
1163*38104Sbostic  * This is only useful for procedures with a varying number of
1164*38104Sbostic  * arguments that are compiled -g.
1165*38104Sbostic  */
1166*38104Sbostic 
1167*38104Sbostic private integer unsafe_evalargs (proc, arglist)
1168*38104Sbostic Symbol proc;
1169*38104Sbostic Node arglist;
1170*38104Sbostic {
1171*38104Sbostic     Node p;
1172*38104Sbostic     integer count;
1173*38104Sbostic 
1174*38104Sbostic     count = 0;
1175*38104Sbostic     for (p = arglist; p != nil; p = p->value.arg[1]) {
1176*38104Sbostic 	assert(p->op == O_COMMA);
1177*38104Sbostic 	eval(p->value.arg[0]);
1178*38104Sbostic 	++count;
1179*38104Sbostic     }
1180*38104Sbostic     return count;
1181*38104Sbostic }
1182*38104Sbostic 
1183*38104Sbostic public procreturn(f)
1184*38104Sbostic Symbol f;
1185*38104Sbostic {
1186*38104Sbostic     integer retvalsize;
1187*38104Sbostic     Node tmp;
1188*38104Sbostic     char *copy;
1189*38104Sbostic 
1190*38104Sbostic     flushoutput();
1191*38104Sbostic     popenv();
1192*38104Sbostic     if (endproc.isfunc) {
1193*38104Sbostic 	retvalsize = size(f->type);
1194*38104Sbostic 	if (retvalsize > sizeof(long)) {
1195*38104Sbostic 	    pushretval(retvalsize, true);
1196*38104Sbostic 	    copy = newarr(char, retvalsize);
1197*38104Sbostic 	    popn(retvalsize, copy);
1198*38104Sbostic 	    tmp = build(O_SCON, copy);
1199*38104Sbostic 	} else {
1200*38104Sbostic 	    tmp = build(O_LCON, (long) (reg(0)));
1201*38104Sbostic 	}
1202*38104Sbostic 	tmp->nodetype = f->type;
1203*38104Sbostic 	tfree(endproc.callnode);
1204*38104Sbostic 	*(endproc.callnode) = *(tmp);
1205*38104Sbostic 	dispose(tmp);
1206*38104Sbostic 	eval(endproc.cmdnode);
1207*38104Sbostic     } else {
1208*38104Sbostic 	putchar('\n');
1209*38104Sbostic 	printname(stdout, f);
1210*38104Sbostic 	printf(" returns successfully\n");
1211*38104Sbostic     }
1212*38104Sbostic     erecover();
1213*38104Sbostic }
1214*38104Sbostic 
1215*38104Sbostic /*
1216*38104Sbostic  * Push the current environment.
1217*38104Sbostic  */
1218*38104Sbostic 
1219*38104Sbostic private pushenv()
1220*38104Sbostic {
1221*38104Sbostic     push(Address, pc);
1222*38104Sbostic     push(Lineno, curline);
1223*38104Sbostic     push(String, cursource);
1224*38104Sbostic     push(Boolean, isstopped);
1225*38104Sbostic     push(Symbol, curfunc);
1226*38104Sbostic     push(Frame, curframe);
1227*38104Sbostic     push(struct Frame, curframerec);
1228*38104Sbostic     push(CallEnv, endproc);
1229*38104Sbostic     push(Word, reg(PROGCTR));
1230*38104Sbostic     push(Word, reg(STKP));
1231*38104Sbostic     push(Word, reg(FRP));
1232*38104Sbostic }
1233*38104Sbostic 
1234*38104Sbostic /*
1235*38104Sbostic  * Pop back to the real world.
1236*38104Sbostic  */
1237*38104Sbostic 
1238*38104Sbostic public popenv()
1239*38104Sbostic {
1240*38104Sbostic     String filename;
1241*38104Sbostic 
1242*38104Sbostic     setreg(FRP, pop(Word));
1243*38104Sbostic     setreg(STKP, pop(Word));
1244*38104Sbostic     setreg(PROGCTR, pop(Word));
1245*38104Sbostic     endproc = pop(CallEnv);
1246*38104Sbostic     curframerec = pop(struct Frame);
1247*38104Sbostic     curframe = pop(Frame);
1248*38104Sbostic     curfunc = pop(Symbol);
1249*38104Sbostic     isstopped = pop(Boolean);
1250*38104Sbostic     filename = pop(String);
1251*38104Sbostic     curline = pop(Lineno);
1252*38104Sbostic     pc = pop(Address);
1253*38104Sbostic     setsource(filename);
1254*38104Sbostic }
1255*38104Sbostic 
1256*38104Sbostic /*
1257*38104Sbostic  * Flush the debuggee's standard output.
1258*38104Sbostic  *
1259*38104Sbostic  * This is VERY dependent on the use of stdio.
1260*38104Sbostic  */
1261*38104Sbostic 
1262*38104Sbostic public flushoutput()
1263*38104Sbostic {
1264*38104Sbostic     Symbol p, iob;
1265*38104Sbostic     Stack *savesp;
1266*38104Sbostic 
1267*38104Sbostic     p = lookup(identname("fflush", true));
1268*38104Sbostic     while (p != nil and not isblock(p)) {
1269*38104Sbostic 	p = p->next_sym;
1270*38104Sbostic     }
1271*38104Sbostic     if (p != nil) {
1272*38104Sbostic 	iob = lookup(identname("_iob", true));
1273*38104Sbostic 	if (iob != nil) {
1274*38104Sbostic 	    pushenv();
1275*38104Sbostic 	    pc = codeloc(p) - FUNCOFFSET;
1276*38104Sbostic 	    savesp = sp;
1277*38104Sbostic 	    push(long, address(iob, nil) + sizeof(*stdout));
1278*38104Sbostic 	    setreg(STKP, reg(STKP) - sizeof(long));
1279*38104Sbostic 	    dwrite(savesp, reg(STKP), sizeof(long));
1280*38104Sbostic 	    sp = savesp;
1281*38104Sbostic 	    beginproc(p, 1);
1282*38104Sbostic 	    stepto(return_addr());
1283*38104Sbostic 	    popenv();
1284*38104Sbostic 	}
1285*38104Sbostic     }
1286*38104Sbostic }
1287