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