home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dosdisas.zip / dccsrcoo.zip / procs.cpp < prev    next >
C/C++ Source or Header  |  1997-04-09  |  11KB  |  423 lines

  1. /*
  2.  *$Log:    procs.c,v $
  3.  * Revision 1.3  94/02/22  15:18:00  cifuente
  4.  * Routines to support propagation of types across arguments.
  5.  * 
  6.  * Revision 1.2  93/12/13  12:25:39  cifuente
  7.  * Interprocedural live analysis finished.
  8.  * 
  9.  * Revision 1.1  93/11/17  16:28:11  cifuente
  10.  * Initial revision
  11.  * 
  12.  * File:    procs.c
  13.  * Purpose: Functions to support Call graphs and procedures
  14.  * Date:    November 1993
  15.  */
  16.  
  17. #include "dcc.h"
  18. #include <string.h>
  19.  
  20.  
  21. /* Static indentation buffer */
  22. #define indSize     61          /* size of indentation buffer; max 20 */
  23. static char indentBuf[indSize] = 
  24.     "                                                            ";
  25.  
  26. static char *indent (Int indLevel)
  27. /* Indentation according to the depth of the statement */
  28.     return (&indentBuf[indSize-(indLevel*3)-1]); 
  29. }
  30.  
  31.  
  32. static void insertArc (PCALL_GRAPH pcallGraph, PPROC newProc)
  33. /* Inserts an outEdge at the current callGraph pointer if the newProc does 
  34.  * not exist.  */
  35. { CALL_GRAPH *pcg;
  36.   Int i;
  37.  
  38.     /* Check if procedure already exists */
  39.     for (i = 0;  i < pcallGraph->numOutEdges; i++)
  40.         if (pcallGraph->outEdges[i]->proc == newProc)
  41.             return;
  42.  
  43.     /* Check if need to allocate more space */
  44.     if (pcallGraph->numOutEdges == pcallGraph->numAlloc)
  45.     {
  46.         pcallGraph->numAlloc += NUM_PROCS_DELTA;
  47.         pcallGraph->outEdges = (PCALL_GRAPH*)reallocVar(pcallGraph->outEdges,
  48.                             pcallGraph->numAlloc * sizeof(PCALL_GRAPH));
  49.         memset (&pcallGraph->outEdges[pcallGraph->numOutEdges], 0,
  50.                 NUM_PROCS_DELTA * sizeof(PCALL_GRAPH));
  51.     }
  52.  
  53.     /* Include new arc */
  54.     pcg = allocStruc(CALL_GRAPH); 
  55.     memset (pcg, 0, sizeof(CALL_GRAPH));
  56.     pcg->proc = newProc;
  57.     pcallGraph->outEdges[pcallGraph->numOutEdges] = pcg;
  58.     pcallGraph->numOutEdges++;
  59. }
  60.  
  61.  
  62. boolT insertCallGraph (PCALL_GRAPH pcallGraph, PPROC caller, PPROC callee)
  63. /* Inserts a (caller, callee) arc in the call graph tree. */
  64. { Int i;
  65.  
  66.     if (pcallGraph->proc == caller)
  67.     {
  68.         insertArc (pcallGraph, callee);
  69.         return (TRUE);
  70.     }
  71.     else
  72.     {
  73.         for (i = 0; i < pcallGraph->numOutEdges; i++)
  74.             if (insertCallGraph (pcallGraph->outEdges[i], caller, callee))
  75.                 return (TRUE);
  76.         return (FALSE);
  77.     }
  78. }
  79.  
  80.  
  81. static void writeNodeCallGraph (PCALL_GRAPH pcallGraph, Int indIdx) 
  82. /* Displays the current node of the call graph, and invokes recursively on
  83.  * the nodes the procedure invokes. */
  84. { Int i;
  85.  
  86.     printf ("%s%s\n", indent(indIdx), pcallGraph->proc->name);
  87.     for (i = 0; i < pcallGraph->numOutEdges; i++)
  88.         writeNodeCallGraph (pcallGraph->outEdges[i], indIdx + 1);
  89. }
  90.  
  91.  
  92. void writeCallGraph (PCALL_GRAPH pcallGraph)
  93. /* Writes the header and invokes recursive procedure */
  94.     printf ("\nCall Graph:\n");
  95.     writeNodeCallGraph (pcallGraph, 0); 
  96. }
  97.  
  98.  
  99. /**************************************************************************
  100.  *  Routines to support arguments 
  101.  *************************************************************************/
  102.  
  103. void newRegArg (PPROC pproc, PICODE picode, PICODE ticode)
  104. /* Updates the argument table by including the register(s) (ie. lhs of
  105.  * picode) and the actual expression (ie. rhs of picode).
  106.  * Note: register(s) are only included once in the table.   */
  107. { COND_EXPR *lhs;
  108.   PSTKFRAME ps, ts;
  109.   ID *id;
  110.   Int i, tidx;
  111.   boolT regExist;
  112.   condId type;
  113.   PPROC tproc;
  114.   byte regL, regH;        /* Registers involved in arguments */
  115.  
  116.     /* Flag ticode as having register arguments */
  117.     tproc = ticode->ic.hl.oper.call.proc;
  118.     tproc->flg |= REG_ARGS;
  119.  
  120.     /* Get registers and index into target procedure's local list */
  121.     ps = ticode->ic.hl.oper.call.args;
  122.     ts = &tproc->args;
  123.     lhs = picode->ic.hl.oper.asgn.lhs;
  124.     type = lhs->expr.ident.idType;
  125.     if (type == REGISTER)
  126.     {
  127.         regL = pproc->localId.id[lhs->expr.ident.idNode.regiIdx].id.regi;
  128.         if (regL < rAL)
  129.             tidx = newByteWordRegId (&tproc->localId, TYPE_WORD_SIGN, regL);
  130.         else
  131.             tidx = newByteWordRegId (&tproc->localId, TYPE_BYTE_SIGN, regL);
  132.     }
  133.     else if (type == LONG_VAR)
  134.     {
  135.         regL = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.l;
  136.         regH = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.h;
  137.         tidx = newLongRegId (&tproc->localId, TYPE_LONG_SIGN, regH, regL, 0);
  138.     }
  139.  
  140.     /* Check if register argument already on the formal argument list */
  141.     regExist = FALSE;
  142.     for (i = 0; i < ts->csym; i++)
  143.     {
  144.         if (type == REGISTER)
  145.         {
  146.             if ((ts->sym[i].regs != NULL) && 
  147.                 (ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx))
  148.             {
  149.                 regExist = TRUE;
  150.                 i = ts->csym;
  151.             }
  152.         }
  153.         else if (type == LONG_VAR)
  154.         {
  155.             if ((ts->sym[i].regs != NULL) && 
  156.                 (ts->sym[i].regs->expr.ident.idNode.longIdx == tidx))
  157.             {
  158.                 regExist = TRUE;
  159.                 i = ts->csym;
  160.             }
  161.         }
  162.     }
  163.  
  164.     /* Do ts (formal arguments) */
  165.     if (regExist == FALSE)
  166.     {
  167.         if (ts->csym == ts->alloc) 
  168.         {
  169.             ts->alloc += 5;
  170.             ts->sym = (STKSYM*)reallocVar(ts->sym, ts->alloc * sizeof(STKSYM));
  171.             memset (&ts->sym[ts->csym], 0, 5 * sizeof(STKSYM));
  172.         }
  173.         sprintf (ts->sym[ts->csym].name, "arg%ld", ts->csym);
  174.         if (type == REGISTER)
  175.         {
  176.             if (regL < rAL)
  177.             {
  178.                 ts->sym[ts->csym].type = TYPE_WORD_SIGN;
  179.                 ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, WORD_REG);
  180.             }
  181.             else
  182.             {
  183.                 ts->sym[ts->csym].type = TYPE_BYTE_SIGN;
  184.                 ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, BYTE_REG);
  185.             }
  186.             sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym);
  187.         }
  188.         else if (type == LONG_VAR)
  189.         {
  190.             ts->sym[ts->csym].regs = idCondExpLongIdx (tidx);
  191.             ts->sym[ts->csym].type = TYPE_LONG_SIGN; 
  192.             sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym);
  193.             propLongId (&tproc->localId, regL, regH,
  194.                                         tproc->localId.id[tidx].name);
  195.         }
  196.  
  197.         ts->csym++;
  198.         ts->numArgs++;
  199.     }
  200.  
  201.     /* Do ps (actual arguments) */
  202.     if (ps->csym == ps->alloc) 
  203.     {
  204.         ps->alloc += 5;
  205.         ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
  206.         memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
  207.     }
  208.     sprintf (ps->sym[ps->csym].name, "arg%ld", ps->csym);
  209.     ps->sym[ps->csym].actual = picode->ic.hl.oper.asgn.rhs;
  210.     ps->sym[ps->csym].regs = lhs;
  211.  
  212.     /* Mask off high and low register(s) in picode */
  213.     switch (type) {
  214.       case REGISTER:    
  215.         id = &pproc->localId.id[lhs->expr.ident.idNode.regiIdx];
  216.         picode->du.def &= maskDuReg[id->id.regi];
  217.         if (id->id.regi < rAL)
  218.             ps->sym[ps->csym].type = TYPE_WORD_SIGN;
  219.         else
  220.             ps->sym[ps->csym].type = TYPE_BYTE_SIGN;
  221.         break;
  222.       case LONG_VAR: 
  223.         id = &pproc->localId.id[lhs->expr.ident.idNode.longIdx];
  224.         picode->du.def &= maskDuReg[id->id.longId.h];
  225.         picode->du.def &= maskDuReg[id->id.longId.l];
  226.         ps->sym[ps->csym].type = TYPE_LONG_SIGN; 
  227.         break;
  228.     }
  229.  
  230.     ps->csym++;
  231.     ps->numArgs++;
  232. }
  233.  
  234.  
  235. void allocStkArgs (PICODE picode, Int num)
  236. /* Allocates num arguments in the actual argument list of the current
  237.  * icode picode.    */
  238. /** NOTE: this function is not used ****/
  239. { PSTKFRAME ps;      
  240.  
  241.     ps = picode->ic.hl.oper.call.args;
  242.     ps->alloc = num;
  243.     ps->csym = num;
  244.     ps->numArgs = num;
  245.     ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
  246.     /**** memset here??? *****/
  247. }
  248.  
  249.  
  250. boolT newStkArg (PICODE picode, COND_EXPR *exp, llIcode opcode, PPROC pproc)
  251. /* Inserts the new expression (ie. the actual parameter) on the argument
  252.  * list.
  253.  * Returns: TRUE if it was a near call that made use of a segment register.
  254.  *            FALSE elsewhere    */
  255. { PSTKFRAME ps;
  256.   byte regi;
  257.  
  258.     /* Check for far procedure call, in which case, references to segment
  259.      * registers are not be considered another parameter (i.e. they are
  260.      * long references to another segment) */
  261.     if (exp)
  262.     {
  263.         if ((exp->type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
  264.         {
  265.             regi =  pproc->localId.id[exp->expr.ident.idNode.regiIdx].id.regi;
  266.             if ((regi >= rES) && (regi <= rDS))
  267.                 if (opcode == iCALLF)
  268.                     return (FALSE);
  269.                 else
  270.                     return (TRUE);
  271.         }
  272.     }
  273.  
  274.     /* Place register argument on the argument list */
  275.     ps = picode->ic.hl.oper.call.args;
  276.     if (ps->csym == ps->alloc) 
  277.     {
  278.         ps->alloc += 5;
  279.         ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
  280.         memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
  281.     }
  282.     ps->sym[ps->csym].actual = exp;
  283.     ps->csym++;
  284.     ps->numArgs++;
  285.     return (FALSE);
  286. }
  287.  
  288.  
  289. void placeStkArg (PICODE picode, COND_EXPR *exp, Int pos)
  290. /* Places the actual argument exp in the position given by pos in the
  291.  * argument list of picode.    */
  292. { PSTKFRAME ps;
  293.  
  294.     ps = picode->ic.hl.oper.call.args;
  295.     ps->sym[pos].actual = exp;
  296.     sprintf (ps->sym[pos].name, "arg%ld", pos);
  297. }
  298.  
  299.  
  300. void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc)
  301. /* Checks to determine whether the expression (actual argument) has the
  302.  * same type as the given type (from the procedure's formal list).  If not,
  303.  * the actual argument gets modified */
  304. { hlType actType;
  305.   Int offset, offL;
  306.  
  307.     if (exp == NULL)
  308.         return;
  309.  
  310.     actType = expType (exp, pproc);
  311.     if ((actType != forType) && (exp->type == IDENTIFIER))
  312.     {
  313.         switch (forType) {
  314.           case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
  315.           case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
  316.           case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
  317.           case TYPE_LONG_UNSIGN: case TYPE_RECORD:
  318.                 break;
  319.  
  320.           case TYPE_PTR:
  321.           case TYPE_CONST:
  322.                 break;
  323.  
  324.           case TYPE_STR:
  325.                 switch (actType) {
  326.                   case TYPE_CONST:
  327.                     /* It's an offset into image where a string is
  328.                      * found.  Point to the string.    */
  329.                     offL = exp->expr.ident.idNode.kte.kte;
  330.                     if (prog.fCOM)
  331.                         offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
  332.                     else
  333.                         offset = (pproc->state.r[rDS]<<4) + offL;
  334.                     exp->expr.ident.idNode.strIdx = offset;
  335.                     exp->expr.ident.idType = STRING;
  336.                     break;
  337.  
  338.                   case TYPE_PTR:
  339.                     /* It's a pointer to a char rather than a pointer to 
  340.                      * an integer */
  341.                     /***HERE - modify the type ****/
  342.                     break;
  343.  
  344.                   case TYPE_WORD_SIGN:
  345.  
  346.                     break;
  347.                 } /* eos */
  348.                 break;
  349.         }
  350.     }
  351. }
  352.  
  353.  
  354. void adjustForArgType (PSTKFRAME pstkFrame, Int numArg, hlType actType)
  355. /* Determines whether the formal argument has the same type as the given
  356.  * type (type of the actual argument).  If not, the formal argument is 
  357.  * changed its type */
  358. { hlType forType;
  359.   PSTKSYM psym, nsym;
  360.   Int off, i;
  361.  
  362.     /* Find stack offset for this argument */
  363.     off = pstkFrame->minOff;
  364.     for (i = 0; i < numArg; i++)
  365.         off += pstkFrame->sym[i].size;
  366.  
  367.     /* Find formal argument */
  368.     if (numArg < pstkFrame->csym)
  369.     {
  370.         psym = &pstkFrame->sym[numArg];
  371.         i = numArg;
  372.         while ((i < pstkFrame->csym) && (psym->off != off))
  373.         {
  374.             psym++;
  375.             i++;
  376.         }
  377.         if (numArg == pstkFrame->csym)
  378.             return;
  379.     }
  380.     /* If formal argument does not exist, do not create new ones, just
  381.      * ignore actual argument */
  382.     else
  383.         return;
  384.  
  385.     forType = psym->type;
  386.     if (forType != actType)
  387.     {
  388.         switch (actType) {
  389.           case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
  390.           case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
  391.           case TYPE_WORD_UNSIGN: case TYPE_RECORD:
  392.                 break;
  393.  
  394.           case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
  395.                 if ((forType == TYPE_WORD_UNSIGN) || 
  396.                     (forType == TYPE_WORD_SIGN) ||
  397.                     (forType == TYPE_UNKNOWN))
  398.                 {
  399.                     /* Merge low and high */
  400.                     psym->type = actType;
  401.                     psym->size = 4;
  402.                     nsym = psym + 1;
  403.                     sprintf (nsym->macro, "HI");
  404.                     sprintf (psym->macro, "LO");
  405.                     nsym->hasMacro = TRUE;
  406.                     psym->hasMacro = TRUE;
  407.                     sprintf (nsym->name, "%s", psym->name);
  408.                     nsym->invalid = TRUE;
  409.                     pstkFrame->numArgs--;
  410.                 }
  411.                 break;
  412.  
  413.           case TYPE_PTR:
  414.           case TYPE_CONST:
  415.           case TYPE_STR:
  416.                 break;
  417.         } /* eos */
  418.     }
  419. }
  420.  
  421.