|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)callproc.c 5.2 (Berkeley) 4/7/87";
9: #endif not lint
10:
11: /*
12: * Evaluate a call to a procedure.
13: *
14: * This file is a botch as far as modularity is concerned.
15: */
16:
17: #include "defs.h"
18: #include "runtime.h"
19: #include "sym.h"
20: #include "tree.h"
21: #include "breakpoint.h"
22: #include "machine.h"
23: #include "process.h"
24: #include "source.h"
25: #include "frame.rep"
26: #include "sym/classes.h"
27: #include "sym/sym.rep"
28: #include "tree/tree.rep"
29: #include "process/process.rep"
30: #include "process/pxinfo.h"
31:
32: LOCAL ADDRESS retaddr;
33: #ifdef tahoe
34: BOOLEAN didret;
35: #endif
36:
37: /*
38: * Controlling logic of procedure calling.
39: * Calling a procedure before ever executing the program must
40: * be special cased.
41: */
42:
43: callproc(procnode, arglist)
44: NODE *procnode;
45: NODE *arglist;
46: {
47: register SYM *proc;
48: #ifdef tahoe
49: register int tmpsp, tmptmp;
50: extern BOOLEAN shouldrestart;
51:
52: if (shouldrestart) {
53: initstart();
54: }
55: #endif
56: if (pc == 0) {
57: curline = firstline(program);
58: setbp(curline);
59: resume();
60: unsetbp(curline);
61: }
62: proc = procnode->nameval;
63: if (!isblock(proc)) {
64: error("\"%s\" is not a procedure or function", proc->symbol);
65: }
66: #ifdef tahoe
67: doret(process);
68: tmpsp = process->sp;
69: #endif
70: pushargs(proc, arglist);
71: #ifdef tahoe
72: tmptmp = tmpsp;
73: tmpsp = process->sp;
74: process->sp = tmptmp;
75: #endif
76: pushenv(proc->symvalue.funcv.codeloc);
77: #ifdef tahoe
78: process->sp = tmpsp;
79: #endif
80: pushframe(proc->blkno);
81: execute(proc);
82: /* NOTREACHED */
83: }
84:
85: /*
86: * Push the arguments on the process' stack. We do this by first
87: * evaluating them on the "eval" stack, then copying into the process'
88: * space.
89: */
90:
91: LOCAL pushargs(proc, arglist)
92: SYM *proc;
93: NODE *arglist;
94: {
95: STACK *savesp;
96: int args_size;
97:
98: savesp = sp;
99: #ifdef tahoe
100: /*
101: * evalargs hopefully keeps stack aligned, so we won't bother
102: * aligning it afterwards, neither will we align process->sp
103: * after subtracting args_size.
104: */
105: #endif
106: evalargs(proc->symbol, proc->chain, arglist);
107: args_size = sp - savesp;
108: process->sp -= args_size;
109: dwrite(savesp, process->sp, args_size);
110: sp = savesp;
111: }
112:
113: /*
114: * Evaluate arguments right-to-left because the eval stack
115: * grows up, px's stack grows down.
116: */
117:
118: LOCAL evalargs(procname, arg, explist)
119: char *procname;
120: SYM *arg;
121: NODE *explist;
122: {
123: NODE *exp;
124: STACK *savesp;
125: ADDRESS addr;
126:
127: if (arg == NIL) {
128: if (explist != NIL) {
129: error("too many parameters to \"%s\"", procname);
130: }
131: } else if (explist == NIL) {
132: error("not enough parameters to \"%s\"", procname);
133: } else {
134: if (explist->op != O_COMMA) {
135: panic("evalargs: arglist missing comma");
136: }
137: savesp = sp;
138: evalargs(procname, arg->chain, explist->right);
139: exp = explist->left;
140: if (!compatible(arg->type, exp->nodetype)) {
141: sp = savesp;
142: trerror("%t is not the same type as parameter \"%s\"",
143: exp, arg->symbol);
144: }
145: if (arg->class == REF) {
146: if (exp->op != O_RVAL) {
147: sp = savesp;
148: error("variable expected for parameter \"%s\"", arg->symbol);
149: }
150: addr = lval(exp->left);
151: push(ADDRESS, addr);
152: } else {
153: eval(exp);
154: }
155: }
156: }
157:
158: /*
159: * Simulate a CALL instruction by pushing the appropriate
160: * stack frame information.
161: *
162: * Massage register 10 or 11 appropriately since it contains the
163: * stack frame pointer.
164: */
165:
166: LOCAL pushframe(b)
167: int b;
168: {
169: ADDRESS *newdp;
170: FRAME callframe;
171:
172: retaddr = program->symvalue.funcv.codeloc;
173:
174: /*
175: * This stuff is set by the callee, just here to take up space.
176: */
177: callframe.stackref = 0;
178: callframe.file = 0;
179: callframe.blockp = 0;
180: callframe.save_loc = NIL;
181: callframe.save_disp = NIL;
182:
183: /*
184: * This is the useful stuff.
185: */
186: callframe.save_dp = curdp();
187: callframe.save_pc = retaddr + ENDOFF;
188: callframe.save_lino = 0;
189: newdp = DISPLAY + (2 * b);
190: dwrite(&newdp, DP, sizeof(newdp));
191: process->sp -= sizeof(callframe);
192: dwrite(&callframe, process->sp, sizeof(callframe));
193: #ifdef tahoe
194: process->reg[11] = process->sp;
195: #else
196: process->reg[10] = process->sp;
197: #endif
198: }
199:
200: /*
201: * Execute the procedure. This routine does NOT return because it
202: * calls "cont", which doesn't return. We set a CALLPROC breakpoint
203: * at "retaddr", the address where the called routine will return.
204: *
205: * The action for a CALLPROC is to call "procreturn" where we restore
206: * the environment.
207: */
208:
209: LOCAL execute(f)
210: SYM *f;
211: {
212: isstopped = TRUE;
213: addbp(retaddr, CALLPROC, f, NIL, NIL, 0);
214: cont();
215: /* NOTREACHED */
216: }
217:
218: procreturn(f)
219: SYM *f;
220: {
221: int len;
222:
223: #ifdef tahoe
224: doret(process);
225: #endif
226: printf("%s returns ", f->symbol);
227: if (f->class == FUNC) {
228: len = size(f->type);
229: dread(sp, process->sp, len);
230: #ifdef tahoe
231: len = (len + 3) & ~3;
232: #endif
233: sp += len;
234: printval(f->type);
235: putchar('\n');
236: } else {
237: printf("successfully\n");
238: }
239: popenv();
240: }
241:
242: /*
243: * Push the current environment.
244: *
245: * This involves both saving pdx and interpreter values.
246: * LOOPADDR is the address of the main interpreter loop.
247: */
248:
249: LOCAL pushenv(newpc)
250: ADDRESS newpc;
251: {
252: #ifdef tahoe
253: /* this should be done somewhere else, but... */
254: INTFP = process->fp;
255: #endif
256: push(ADDRESS, pc);
257: push(LINENO, curline);
258: push(char *, cursource);
259: push(BOOLEAN, isstopped);
260: push(SYM *, curfunc);
261: push(WORD, process->pc);
262: push(WORD, process->sp);
263: process->pc = LOOPADDR;
264: pc = newpc;
265: #ifdef tahoe
266: process->reg[12] = pc + ENDOFF;
267: #else
268: process->reg[11] = pc + ENDOFF;
269: #endif
270: }
271:
272: /*
273: * Pop back to the real world.
274: */
275:
276: popenv()
277: {
278: register PROCESS *p;
279: char *filename;
280:
281: p = process;
282: p->sp = pop(WORD);
283: p->pc = pop(WORD);
284: curfunc = pop(SYM *);
285: isstopped = pop(BOOLEAN);
286: filename = pop(char *);
287: curline = pop(LINENO);
288: pc = pop(ADDRESS);
289: #ifdef tahoe
290: p->reg[12] = pc + 1 + ENDOFF;
291: #endif
292: if (filename != cursource) {
293: skimsource(filename);
294: }
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.