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