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