procs.cpp 11 KB

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