1*22517Sdist /* 2*22517Sdist * Copyright (c) 1980 Regents of the University of California. 3*22517Sdist * All rights reserved. The Berkeley software License Agreement 4*22517Sdist * specifies the terms and conditions for redistribution. 5*22517Sdist */ 65515Slinton 7*22517Sdist #ifndef lint 8*22517Sdist static char sccsid[] = "@(#)callproc.c 5.1 (Berkeley) 06/06/85"; 9*22517Sdist #endif not lint 105515Slinton /* 115515Slinton * Evaluate a call to a procedure. 125515Slinton * 135515Slinton * This file is a botch as far as modularity is concerned. 145515Slinton */ 155515Slinton 165515Slinton #include "defs.h" 175515Slinton #include "runtime.h" 185515Slinton #include "sym.h" 195515Slinton #include "tree.h" 205515Slinton #include "breakpoint.h" 215515Slinton #include "machine.h" 225515Slinton #include "process.h" 235515Slinton #include "source.h" 245515Slinton #include "frame.rep" 255515Slinton #include "sym/classes.h" 265515Slinton #include "sym/sym.rep" 275515Slinton #include "tree/tree.rep" 285515Slinton #include "process/process.rep" 295515Slinton #include "process/pxinfo.h" 305515Slinton 315515Slinton LOCAL ADDRESS retaddr; 325515Slinton 335515Slinton /* 345515Slinton * Controlling logic of procedure calling. 355515Slinton * Calling a procedure before ever executing the program must 365515Slinton * be special cased. 375515Slinton */ 385515Slinton 395515Slinton callproc(procnode, arglist) 405515Slinton NODE *procnode; 415515Slinton NODE *arglist; 425515Slinton { 435515Slinton SYM *proc; 445515Slinton 455515Slinton if (pc == 0) { 465515Slinton curline = firstline(program); 475515Slinton setbp(curline); 485515Slinton resume(); 495515Slinton unsetbp(curline); 505515Slinton } 515515Slinton proc = procnode->nameval; 525515Slinton if (!isblock(proc)) { 535515Slinton error("\"%s\" is not a procedure or function", proc->symbol); 545515Slinton } 555659Slinton pushargs(proc, arglist); 565515Slinton pushenv(proc->symvalue.funcv.codeloc); 575515Slinton pushframe(proc->blkno); 585515Slinton execute(proc); 595515Slinton /* NOTREACHED */ 605515Slinton } 615515Slinton 625515Slinton /* 635515Slinton * Push the arguments on the process' stack. We do this by first 645515Slinton * evaluating them on the "eval" stack, then copying into the process' 655515Slinton * space. 665515Slinton */ 675515Slinton 685515Slinton LOCAL pushargs(proc, arglist) 695515Slinton SYM *proc; 705515Slinton NODE *arglist; 715515Slinton { 725515Slinton STACK *savesp; 735515Slinton int args_size; 745515Slinton 755515Slinton savesp = sp; 765515Slinton evalargs(proc->symbol, proc->chain, arglist); 775515Slinton args_size = sp - savesp; 785515Slinton process->sp -= args_size; 795515Slinton dwrite(savesp, process->sp, args_size); 805515Slinton sp = savesp; 815515Slinton } 825515Slinton 835515Slinton /* 845515Slinton * Evaluate arguments right-to-left because the eval stack 855515Slinton * grows up, px's stack grows down. 865515Slinton */ 875515Slinton 885515Slinton LOCAL evalargs(procname, arg, explist) 895515Slinton char *procname; 905515Slinton SYM *arg; 915515Slinton NODE *explist; 925515Slinton { 935515Slinton NODE *exp; 945515Slinton STACK *savesp; 955515Slinton ADDRESS addr; 965515Slinton 975515Slinton if (arg == NIL) { 985515Slinton if (explist != NIL) { 995515Slinton error("too many parameters to \"%s\"", procname); 1005515Slinton } 1015515Slinton } else if (explist == NIL) { 1025515Slinton error("not enough parameters to \"%s\"", procname); 1035515Slinton } else { 1045515Slinton if (explist->op != O_COMMA) { 1055515Slinton panic("evalargs: arglist missing comma"); 1065515Slinton } 1075515Slinton savesp = sp; 1085515Slinton evalargs(procname, arg->chain, explist->right); 1095515Slinton exp = explist->left; 1105515Slinton if (!compatible(arg->type, exp->nodetype)) { 1115515Slinton sp = savesp; 1125515Slinton trerror("%t is not the same type as parameter \"%s\"", 1135515Slinton exp, arg->symbol); 1145515Slinton } 1155515Slinton if (arg->class == REF) { 1165515Slinton if (exp->op != O_RVAL) { 1175515Slinton sp = savesp; 1185515Slinton error("variable expected for parameter \"%s\"", arg->symbol); 1195515Slinton } 1205515Slinton addr = lval(exp->left); 1215515Slinton push(ADDRESS, addr); 1225515Slinton } else { 1235515Slinton eval(exp); 1245515Slinton } 1255515Slinton } 1265515Slinton } 1275515Slinton 1285515Slinton /* 1295515Slinton * Simulate a CALL instruction by pushing the appropriate 1305515Slinton * stack frame information. 1315515Slinton * 1325515Slinton * Massage register 10 appropriately since it contains the 1335515Slinton * stack frame pointer. 1345515Slinton */ 1355515Slinton 1365515Slinton LOCAL pushframe(b) 1375515Slinton int b; 1385515Slinton { 1395515Slinton ADDRESS *newdp; 1405515Slinton FRAME callframe; 1415515Slinton 1425515Slinton retaddr = program->symvalue.funcv.codeloc; 1435515Slinton 1445515Slinton /* 1455515Slinton * This stuff is set by the callee, just here to take up space. 1465515Slinton */ 1475515Slinton callframe.stackref = 0; 1485515Slinton callframe.file = 0; 1495515Slinton callframe.blockp = 0; 1505515Slinton callframe.save_loc = NIL; 1515515Slinton callframe.save_disp = NIL; 1525515Slinton 1535515Slinton /* 1545515Slinton * This is the useful stuff. 1555515Slinton */ 1565515Slinton callframe.save_dp = curdp(); 1575515Slinton callframe.save_pc = retaddr + ENDOFF; 1585515Slinton callframe.save_lino = 0; 1595515Slinton newdp = DISPLAY + (2 * b); 1605515Slinton dwrite(&newdp, DP, sizeof(newdp)); 1615515Slinton process->sp -= sizeof(callframe); 1625515Slinton dwrite(&callframe, process->sp, sizeof(callframe)); 1635515Slinton process->reg[10] = process->sp; 1645515Slinton } 1655515Slinton 1665515Slinton /* 1675515Slinton * Execute the procedure. This routine does NOT return because it 1685515Slinton * calls "cont", which doesn't return. We set a CALLPROC breakpoint 1695515Slinton * at "retaddr", the address where the called routine will return. 1705515Slinton * 1715515Slinton * The action for a CALLPROC is to call "procreturn" where we restore 1725515Slinton * the environment. 1735515Slinton */ 1745515Slinton 1755515Slinton LOCAL execute(f) 1765515Slinton SYM *f; 1775515Slinton { 1785515Slinton isstopped = TRUE; 1795515Slinton addbp(retaddr, CALLPROC, f, NIL, NIL, 0); 1805515Slinton cont(); 1815515Slinton /* NOTREACHED */ 1825515Slinton } 1835515Slinton 1845515Slinton procreturn(f) 1855515Slinton SYM *f; 1865515Slinton { 1875515Slinton int len; 1885515Slinton 1895515Slinton printf("%s returns ", f->symbol); 1905515Slinton if (f->class == FUNC) { 1915515Slinton len = size(f->type); 1925515Slinton dread(sp, process->sp, len); 1935515Slinton sp += len; 1945515Slinton printval(f->type); 1955515Slinton putchar('\n'); 1965515Slinton } else { 1975515Slinton printf("successfully\n"); 1985515Slinton } 1995515Slinton popenv(); 2005515Slinton } 2015515Slinton 2025515Slinton /* 2035515Slinton * Push the current environment. 2045515Slinton * 2055515Slinton * This involves both saving pdx and interpreter values. 2065515Slinton * LOOPADDR is the address of the main interpreter loop. 2075515Slinton */ 2085515Slinton 2095515Slinton LOCAL pushenv(newpc) 2105515Slinton ADDRESS newpc; 2115515Slinton { 2125515Slinton push(ADDRESS, pc); 2135515Slinton push(LINENO, curline); 2145515Slinton push(char *, cursource); 2155515Slinton push(BOOLEAN, isstopped); 2165515Slinton push(SYM *, curfunc); 2175515Slinton push(WORD, process->pc); 2185515Slinton push(WORD, process->sp); 2195515Slinton process->pc = LOOPADDR; 2205515Slinton pc = newpc; 2215515Slinton process->reg[11] = pc + ENDOFF; 2225515Slinton } 2235515Slinton 2245515Slinton /* 2255515Slinton * Pop back to the real world. 2265515Slinton */ 2275515Slinton 2285515Slinton popenv() 2295515Slinton { 2305515Slinton register PROCESS *p; 2315515Slinton char *filename; 2325515Slinton 2335515Slinton p = process; 2345515Slinton p->sp = pop(WORD); 2355515Slinton p->pc = pop(WORD); 2365515Slinton curfunc = pop(SYM *); 2375515Slinton isstopped = pop(BOOLEAN); 2385515Slinton filename = pop(char *); 2395515Slinton curline = pop(LINENO); 2405515Slinton pc = pop(ADDRESS); 2415515Slinton if (filename != cursource) { 2425515Slinton skimsource(filename); 2435515Slinton } 2445515Slinton } 245