procs.cpp 12 KB

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