123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- * File: procs.c
- * Purpose: Functions to support Call graphs and procedures
- * Date: November 1993
- * (C) Cristina Cifuentes
- */
- #include <cstring>
- #include <cassert>
- #include "dcc.h"
- /* Static indentation buffer */
- #define indSize 61 /* size of indentation buffer; max 20 */
- static char indentBuf[indSize] =
- " ";
- static char *indent (Int indLevel)
- /* Indentation according to the depth of the statement */
- {
- return (&indentBuf[indSize-(indLevel*3)-1]);
- }
- /* Inserts an outEdge at the current callGraph pointer if the newProc does
- * not exist. */
- void CALL_GRAPH::insertArc (ilFunction newProc)
- {
- CALL_GRAPH *pcg;
- Int i;
- /* Check if procedure already exists */
- auto res=std::find_if(outEdges.begin(),outEdges.end(),[newProc](CALL_GRAPH *e) {return e->proc==newProc;});
- if(res!=outEdges.end())
- return;
- /* Include new arc */
- pcg = new CALL_GRAPH;
- pcg->proc = newProc;
- outEdges.push_back(pcg);
- }
- /* Inserts a (caller, callee) arc in the call graph tree. */
- boolT CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
- {
- Int i;
- if (proc == caller)
- {
- insertArc (callee);
- return true;
- }
- else
- {
- for (i = 0; i < outEdges.size(); i++)
- if (outEdges[i]->insertCallGraph (caller, callee))
- return true;
- return (false);
- }
- }
- boolT CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
- {
- auto iter = std::find_if(pProcList.begin(),pProcList.end(),
- [caller](const Function &f)->bool {return caller==&f;});
- assert(iter!=pProcList.end());
- return insertCallGraph(iter,callee);
- }
- /* Displays the current node of the call graph, and invokes recursively on
- * the nodes the procedure invokes. */
- void CALL_GRAPH::writeNodeCallGraph(Int indIdx)
- {
- Int i;
- printf ("%s%s\n", indent(indIdx), proc->name.c_str());
- for (i = 0; i < outEdges.size(); i++)
- outEdges[i]->writeNodeCallGraph (indIdx + 1);
- }
- /* Writes the header and invokes recursive procedure */
- void CALL_GRAPH::write()
- {
- printf ("\nCall Graph:\n");
- writeNodeCallGraph (0);
- }
- /**************************************************************************
- * Routines to support arguments
- *************************************************************************/
- /* Updates the argument table by including the register(s) (ie. lhs of
- * picode) and the actual expression (ie. rhs of picode).
- * Note: register(s) are only included once in the table. */
- void Function::newRegArg(ICODE *picode, ICODE *ticode)
- {
- COND_EXPR *lhs;
- STKFRAME * ps, *ts;
- ID *id;
- Int i, tidx;
- boolT regExist;
- condId type;
- Function * tproc;
- byte regL, regH; /* Registers involved in arguments */
- /* Flag ticode as having register arguments */
- tproc = ticode->ic.hl.oper.call.proc;
- tproc->flg |= REG_ARGS;
- /* Get registers and index into target procedure's local list */
- ps = ticode->ic.hl.oper.call.args;
- ts = &tproc->args;
- lhs = picode->ic.hl.oper.asgn.lhs;
- type = lhs->expr.ident.idType;
- if (type == REGISTER)
- {
- regL = localId.id_arr[lhs->expr.ident.idNode.regiIdx].id.regi;
- if (regL < rAL)
- tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
- else
- tidx = tproc->localId.newByteWordReg(TYPE_BYTE_SIGN, regL);
- }
- else if (type == LONG_VAR)
- {
- regL = localId.id_arr[lhs->expr.ident.idNode.longIdx].id.longId.l;
- regH = localId.id_arr[lhs->expr.ident.idNode.longIdx].id.longId.h;
- tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regH, regL, Icode.begin() /*0*/);
- }
- /* Check if register argument already on the formal argument list */
- regExist = FALSE;
- for (i = 0; i < ts->sym.size(); i++)
- {
- if (type == REGISTER)
- {
- if ((ts->sym[i].regs != NULL) &&
- (ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx))
- {
- regExist = TRUE;
- i = ts->sym.size();
- }
- }
- else if (type == LONG_VAR)
- {
- if ((ts->sym[i].regs != NULL) &&
- (ts->sym[i].regs->expr.ident.idNode.longIdx == tidx))
- {
- regExist = TRUE;
- i = ts->sym.size();
- }
- }
- }
- /* Do ts (formal arguments) */
- if (regExist == FALSE)
- {
- STKSYM newsym;
- sprintf (newsym.name, "arg%ld", ts->sym.size());
- if (type == REGISTER)
- {
- if (regL < rAL)
- {
- newsym.type = TYPE_WORD_SIGN;
- newsym.regs = COND_EXPR::idRegIdx(tidx, WORD_REG);
- }
- else
- {
- newsym.type = TYPE_BYTE_SIGN;
- newsym.regs = COND_EXPR::idRegIdx(tidx, BYTE_REG);
- }
- sprintf (tproc->localId.id_arr[tidx].name, "arg%ld", ts->sym.size());
- }
- else if (type == LONG_VAR)
- {
- newsym.regs = COND_EXPR::idLongIdx (tidx);
- newsym.type = TYPE_LONG_SIGN;
- sprintf (tproc->localId.id_arr[tidx].name, "arg%ld", ts->sym.size());
- tproc->localId.propLongId (regL, regH,
- tproc->localId.id_arr[tidx].name);
- }
- ts->sym.push_back(newsym);
- ts->numArgs++;
- }
- /* Do ps (actual arguments) */
- STKSYM newsym;
- sprintf (newsym.name, "arg%ld", ps->sym.size());
- newsym.actual = picode->ic.hl.oper.asgn.rhs;
- newsym.regs = lhs;
- /* Mask off high and low register(s) in picode */
- switch (type) {
- case REGISTER:
- id = &localId.id_arr[lhs->expr.ident.idNode.regiIdx];
- picode->du.def &= maskDuReg[id->id.regi];
- if (id->id.regi < rAL)
- newsym.type = TYPE_WORD_SIGN;
- else
- newsym.type = TYPE_BYTE_SIGN;
- break;
- case LONG_VAR:
- id = &localId.id_arr[lhs->expr.ident.idNode.longIdx];
- picode->du.def &= maskDuReg[id->id.longId.h];
- picode->du.def &= maskDuReg[id->id.longId.l];
- newsym.type = TYPE_LONG_SIGN;
- break;
- }
- ps->sym.push_back(newsym);
- ps->numArgs++;
- }
- /* Allocates num arguments in the actual argument list of the current
- * icode picode. */
- /** NOTE: this function is not used ****/
- void allocStkArgs (ICODE *picode, Int num)
- {
- STKFRAME * ps;
- ps = picode->ic.hl.oper.call.args;
- ps->numArgs = num;
- ps->sym.resize(num);
- }
- /* Inserts the new expression (ie. the actual parameter) on the argument
- * list.
- * Returns: TRUE if it was a near call that made use of a segment register.
- * FALSE elsewhere */
- boolT newStkArg (ICODE *picode, COND_EXPR *exp, llIcode opcode, Function * pproc)
- {
- STKFRAME * ps;
- byte regi;
- /* Check for far procedure call, in which case, references to segment
- * registers are not be considered another parameter (i.e. they are
- * long references to another segment) */
- if (exp)
- {
- if ((exp->type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
- {
- regi = pproc->localId.id_arr[exp->expr.ident.idNode.regiIdx].id.regi;
- if ((regi >= rES) && (regi <= rDS))
- if (opcode == iCALLF)
- return false;
- else
- return true;
- }
- }
- /* Place register argument on the argument list */
- ps = picode->ic.hl.oper.call.args;
- STKSYM newsym;
- newsym.actual = exp;
- ps->sym.push_back(newsym);
- ps->numArgs++;
- return false;
- }
- /* Places the actual argument exp in the position given by pos in the
- * argument list of picode. */
- void placeStkArg (ICODE *picode, COND_EXPR *exp, Int pos)
- { STKFRAME * ps;
- ps = picode->ic.hl.oper.call.args;
- ps->sym[pos].actual = exp;
- sprintf (ps->sym[pos].name, "arg%ld", pos);
- }
- /* Checks to determine whether the expression (actual argument) has the
- * same type as the given type (from the procedure's formal list). If not,
- * the actual argument gets modified */
- void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
- {
- hlType actType;
- Int offset, offL;
- if (exp == NULL)
- return;
- actType = expType (exp, pproc);
- if (((actType == forType) || (exp->type != IDENTIFIER)))
- return;
- switch (forType)
- {
- case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
- case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
- case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
- case TYPE_LONG_UNSIGN: case TYPE_RECORD:
- break;
- case TYPE_PTR:
- case TYPE_CONST:
- break;
- case TYPE_STR:
- switch (actType) {
- case TYPE_CONST:
- /* It's an offset into image where a string is
- * found. Point to the string. */
- offL = exp->expr.ident.idNode.kte.kte;
- if (prog.fCOM)
- offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
- else
- offset = (pproc->state.r[rDS]<<4) + offL;
- exp->expr.ident.idNode.strIdx = offset;
- exp->expr.ident.idType = STRING;
- break;
- case TYPE_PTR:
- /* It's a pointer to a char rather than a pointer to
- * an integer */
- /***HERE - modify the type ****/
- break;
- case TYPE_WORD_SIGN:
- break;
- } /* eos */
- break;
- }
- }
- /* Determines whether the formal argument has the same type as the given
- * type (type of the actual argument). If not, the formal argument is
- * changed its type */
- void STKFRAME::adjustForArgType(Int numArg_, hlType actType_)
- {
- hlType forType;
- STKSYM * psym, * nsym;
- Int off, i;
- /* Find stack offset for this argument */
- off = minOff;
- for (i = 0; i < numArg_; i++)
- off += sym[i].size;
- /* Find formal argument */
- if (numArg_ < sym.size())
- {
- psym = &sym[numArg_];
- i = numArg_;
- while ((i < sym.size()) && (psym->off != off))
- {
- psym++;
- i++;
- }
- if (numArg_ == sym.size())
- return;
- }
- /* If formal argument does not exist, do not create new ones, just
- * ignore actual argument */
- else
- return;
- forType = psym->type;
- if (forType != actType_)
- {
- switch (actType_) {
- case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
- case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
- case TYPE_WORD_UNSIGN: case TYPE_RECORD:
- break;
- case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
- if ((forType == TYPE_WORD_UNSIGN) ||
- (forType == TYPE_WORD_SIGN) ||
- (forType == TYPE_UNKNOWN))
- {
- /* Merge low and high */
- psym->type = actType_;
- psym->size = 4;
- nsym = psym + 1;
- sprintf (nsym->macro, "HI");
- sprintf (psym->macro, "LO");
- nsym->hasMacro = TRUE;
- psym->hasMacro = TRUE;
- sprintf (nsym->name, "%s", psym->name);
- nsym->invalid = TRUE;
- numArgs--;
- }
- break;
- case TYPE_PTR:
- case TYPE_CONST:
- case TYPE_STR:
- break;
- } /* eos */
- }
- }
|