procs.cpp 11 KB

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