dataflow.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. /*****************************************************************************
  2. * Project: dcc
  3. * File: dataflow.c
  4. * Purpose: Data flow analysis module.
  5. * (C) Cristina Cifuentes
  6. ****************************************************************************/
  7. #include <stdint.h>
  8. #include <cstring>
  9. #include <iostream>
  10. #include <iomanip>
  11. #include <cstdio>
  12. #include <boost/range.hpp>
  13. #include <boost/range/adaptors.hpp>
  14. #include <boost/range/algorithm.hpp>
  15. #include <boost/assign.hpp>
  16. #include "dcc.h"
  17. #include "project.h"
  18. using namespace boost;
  19. using namespace boost::adaptors;
  20. struct ExpStack
  21. {
  22. Function *func;
  23. typedef std::list<Expr *> EXP_STK;
  24. EXP_STK expStk; /* local expression stack */
  25. void init(Function *f);
  26. void push(Expr *);
  27. Expr * pop();
  28. Expr * top() const {
  29. if(!expStk.empty())
  30. return expStk.back();
  31. return nullptr;
  32. }
  33. int numElem();
  34. bool empty();
  35. void processExpPush(int &numHlIcodes, ICODE &picode)
  36. {
  37. RegisterNode *rn = dynamic_cast<RegisterNode *>(picode.hlU()->expr());
  38. if(rn)
  39. assert(rn->m_syms==&func->localId);
  40. push(picode.hlU()->expr());
  41. picode.invalidate();
  42. numHlIcodes--;
  43. }
  44. };
  45. /***************************************************************************
  46. * Expression stack functions
  47. **************************************************************************/
  48. /* Reinitalizes the expression stack (expStk) to NULL, by freeing all the
  49. * space allocated (if any). */
  50. void ExpStack::init(Function *f)
  51. {
  52. func=f;
  53. expStk.clear();
  54. }
  55. /* Pushes the given expression onto the local stack (expStk). */
  56. void ExpStack::push(Expr *expr)
  57. {
  58. expStk.push_back(expr);
  59. }
  60. /* Returns the element on the top of the local expression stack (expStk),
  61. * and deallocates the space allocated by this node.
  62. * If there are no elements on the stack, returns NULL. */
  63. Expr *ExpStack::pop()
  64. {
  65. if(expStk.empty())
  66. return nullptr;
  67. Expr *topExp = expStk.back();
  68. expStk.pop_back();
  69. return topExp;
  70. }
  71. /* Returns the number of elements available in the expression stack */
  72. int ExpStack::numElem()
  73. {
  74. return expStk.size();
  75. }
  76. /* Returns whether the expression stack is empty or not */
  77. bool ExpStack::empty()
  78. {
  79. return expStk.empty();
  80. }
  81. using namespace std;
  82. ExpStack g_exp_stk;
  83. /* Returns the index of the local variable or parameter at offset off, if it
  84. * is in the stack frame provided. */
  85. size_t STKFRAME::getLocVar(int off)
  86. {
  87. auto iter=findByLabel(off);
  88. return distance(begin(),iter);
  89. }
  90. /* Returns a string with the source operand of Icode */
  91. static Expr *srcIdent (const LLInst &ll_insn, Function * pProc, iICODE i, ICODE & duIcode, operDu du)
  92. {
  93. const LLOperand * src_op = ll_insn.get(SRC);
  94. if (src_op->isImmediate()) /* immediate operand ll_insn.testFlags(I)*/
  95. {
  96. //if (ll_insn.testFlags(B))
  97. return new Constant(src_op->getImm2(), src_op->byteWidth());
  98. }
  99. // otherwise
  100. return AstIdent::id (ll_insn, SRC, pProc, i, duIcode, du);
  101. }
  102. /* Returns the destination operand */
  103. static Expr *dstIdent (const LLInst & ll_insn, Function * pProc, iICODE i, ICODE & duIcode, operDu du)
  104. {
  105. Expr *n;
  106. n = AstIdent::id (ll_insn, DST, pProc, i, duIcode, du);
  107. /** Is it needed? (pIcode->ll()->flg) & NO_SRC_B **/
  108. return (n);
  109. }
  110. /* Eliminates all condition codes and generates new hlIcode instructions */
  111. void Function::elimCondCodes ()
  112. {
  113. // int i;
  114. uint8_t use; /* Used flags bit vector */
  115. uint8_t def; /* Defined flags bit vector */
  116. bool notSup; /* Use/def combination not supported */
  117. Expr *rhs; /* Source operand */
  118. Expr *lhs; /* Destination operand */
  119. BinaryOperator *_expr; /* Boolean expression */
  120. //BB * pBB; /* Pointer to BBs in dfs last ordering */
  121. riICODE useAt; /* Instruction that used flag */
  122. riICODE defAt; /* Instruction that defined flag */
  123. //lhs=rhs=_expr=0;
  124. auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) );
  125. for( BB * pBB : valid_reversed_bbs)
  126. {
  127. //auto reversed_instructions = pBB->range() | reversed;
  128. for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++)
  129. {
  130. llIcode useAtOp = llIcode(useAt->ll()->getOpcode());
  131. use = useAt->ll()->flagDU.u;
  132. if ((useAt->type != LOW_LEVEL) || ( ! useAt->valid() ) || ( 0 == use ))
  133. continue;
  134. /* Find definition within the same basic block */
  135. defAt=useAt;
  136. ++defAt;
  137. for (; defAt != pBB->rend(); defAt++)
  138. {
  139. ICODE &defIcode(*defAt);
  140. def = defAt->ll()->flagDU.d;
  141. if ((use & def) != use)
  142. continue;
  143. notSup = false;
  144. LLOperand *dest_ll = defIcode.ll()->get(DST);
  145. if ((useAtOp >= iJB) && (useAtOp <= iJNS))
  146. {
  147. iICODE befDefAt = (++riICODE(defAt)).base();
  148. switch (defIcode.ll()->getOpcode())
  149. {
  150. case iCMP:
  151. rhs = srcIdent (*defIcode.ll(), this, befDefAt,*useAt, eUSE);
  152. lhs = dstIdent (*defIcode.ll(), this, befDefAt,*useAt, eUSE);
  153. break;
  154. case iOR:
  155. lhs = defIcode.hl()->asgn.lhs()->clone();
  156. useAt->copyDU(*defAt, eUSE, eDEF);
  157. //if (defAt->ll()->testFlags(B))
  158. rhs = new Constant(0, dest_ll->byteWidth());
  159. break;
  160. case iTEST:
  161. rhs = srcIdent (*defIcode.ll(),this, befDefAt,*useAt, eUSE);
  162. lhs = dstIdent (*defIcode.ll(),this, befDefAt,*useAt, eUSE);
  163. lhs = BinaryOperator::And(lhs, rhs);
  164. // if (defAt->ll()->testFlags(B))
  165. rhs = new Constant(0, dest_ll->byteWidth());
  166. break;
  167. case iINC:
  168. case iDEC: //WARNING: verbatim copy from iOR needs fixing ?
  169. lhs = defIcode.hl()->asgn.lhs()->clone();
  170. useAt->copyDU(*defAt, eUSE, eDEF);
  171. rhs = new Constant(0, dest_ll->byteWidth());
  172. break;
  173. default:
  174. notSup = true;
  175. std::cout << hex<<defIcode.loc_ip;
  176. reportError (JX_NOT_DEF, defIcode.ll()->getOpcode());
  177. flg |= PROC_ASM; /* generate asm */
  178. }
  179. if (! notSup)
  180. {
  181. assert(lhs);
  182. assert(rhs);
  183. _expr = BinaryOperator::Create(condOpJCond[useAtOp-iJB],lhs,rhs);
  184. useAt->setJCond(_expr);
  185. }
  186. }
  187. else if (useAtOp == iJCXZ)
  188. {
  189. //NOTICE: was rCX, 0
  190. lhs = new RegisterNode(LLOperand(rCX, 0 ), &localId);
  191. useAt->setRegDU (rCX, eUSE);
  192. rhs = new Constant(0, 2);
  193. _expr = BinaryOperator::Create(EQUAL,lhs,rhs);
  194. useAt->setJCond(_expr);
  195. }
  196. // else if (useAt->getOpcode() == iRCL)
  197. // {
  198. // }
  199. else
  200. {
  201. ICODE &a(*defAt);
  202. ICODE &b(*useAt);
  203. reportError (NOT_DEF_USE,a.ll()->getOpcode(),b.ll()->getOpcode());
  204. flg |= PROC_ASM; /* generate asm */
  205. }
  206. break;
  207. }
  208. /* Check for extended basic block */
  209. if ((pBB->size() == 1) &&(useAtOp >= iJB) && (useAtOp <= iJNS))
  210. {
  211. ICODE & _prev(pBB->back()); /* For extended basic blocks - previous icode inst */
  212. if (_prev.hl()->opcode == HLI_JCOND)
  213. {
  214. _expr = dynamic_cast<BinaryOperator *>(_prev.hl()->expr()->clone());
  215. assert(_expr);
  216. _expr->changeBoolOp (condOpJCond[useAtOp-iJB]);
  217. useAt->copyDU(_prev, eUSE, eUSE);
  218. useAt->setJCond(_expr);
  219. }
  220. }
  221. /* Error - definition not found for use of a cond code */
  222. else if (defAt == pBB->rend())
  223. {
  224. reportError(DEF_NOT_FOUND,useAtOp);
  225. }
  226. }
  227. }
  228. }
  229. /** Generates the LiveUse() and Def() sets for each basic block in the graph.
  230. \note these sets are constant and could have been constructed during
  231. the construction of the graph, but since the code hasn't been
  232. analyzed yet for idioms, the procedure preamble misleads the
  233. analysis (eg: push si, would include si in LiveUse; although it
  234. is not really meant to be a register that is used before defined). */
  235. void Function::genLiveKtes ()
  236. {
  237. BB * pbb;
  238. LivenessSet liveUse, def;
  239. for (size_t i = 0; i < numBBs; i++)
  240. {
  241. liveUse.reset();
  242. def.reset();
  243. pbb = m_dfsLast[i];
  244. if (pbb->flg & INVALID_BB)
  245. continue; // skip invalid BBs
  246. for(ICODE &insn : *pbb)
  247. {
  248. if ((insn.type == HIGH_LEVEL) && ( insn.valid() ))
  249. {
  250. liveUse |= (insn.du.use - def);
  251. def |= insn.du.def;
  252. }
  253. }
  254. pbb->liveUse = liveUse;
  255. pbb->def = def;
  256. }
  257. }
  258. /* Generates the liveIn() and liveOut() sets for each basic block via an
  259. * iterative approach.
  260. * Propagates register usage information to the procedure call. */
  261. void Function::liveRegAnalysis (LivenessSet &in_liveOut)
  262. {
  263. using namespace boost::adaptors;
  264. using namespace boost::assign;
  265. //BB * pbb=0; /* pointer to current basic block */
  266. Function * pcallee; /* invoked subroutine */
  267. //ICODE *ticode /* icode that invokes a subroutine */
  268. ;
  269. LivenessSet prevLiveOut, /* previous live out */
  270. prevLiveIn; /* previous live in */
  271. bool change; /* is there change in the live sets?*/
  272. /* liveOut for this procedure */
  273. liveOut = in_liveOut;
  274. change = true;
  275. while (change)
  276. {
  277. /* Process nodes in reverse postorder order */
  278. change = false;
  279. auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) );
  280. for( BB * pbb : valid_reversed_bbs) // for each valid pbb in reversed dfs order
  281. {
  282. /* Get current liveIn() and liveOut() sets */
  283. prevLiveIn = pbb->liveIn;
  284. prevLiveOut = pbb->liveOut;
  285. /* liveOut(b) = U LiveIn(s); where s is successor(b)
  286. * liveOut(b) = {liveOut}; when b is a HLI_RET node */
  287. if (pbb->edges.empty()) /* HLI_RET node */
  288. {
  289. pbb->liveOut = in_liveOut;
  290. /* Get return expression of function */
  291. if (flg & PROC_IS_FUNC)
  292. {
  293. auto picode = pbb->rbegin(); /* icode of function return */
  294. if (picode->hl()->opcode == HLI_RET)
  295. {
  296. picode->hlU()->expr(AstIdent::idID(&retVal, &localId, (++pbb->rbegin()).base()));
  297. picode->du.use = in_liveOut;
  298. }
  299. }
  300. }
  301. else /* Check successors */
  302. {
  303. for(TYPEADR_TYPE &e : pbb->edges)
  304. {
  305. pbb->liveOut |= e.BBptr->liveIn;
  306. }
  307. /* propagate to invoked procedure */
  308. if (pbb->nodeType == CALL_NODE)
  309. {
  310. ICODE &ticode(pbb->back());
  311. pcallee = ticode.hl()->call.proc;
  312. /* user/runtime routine */
  313. if (! (pcallee->flg & PROC_ISLIB))
  314. {
  315. if (pcallee->liveAnal == false) /* hasn't been processed */
  316. pcallee->dataFlow (pbb->liveOut);
  317. pbb->liveOut = pcallee->liveIn;
  318. }
  319. else /* library routine */
  320. {
  321. if ( (pcallee->flg & PROC_IS_FUNC) && /* returns a value */
  322. (pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any()
  323. )
  324. pbb->liveOut = pcallee->liveOut;
  325. else
  326. pbb->liveOut.reset();
  327. }
  328. if ((! (pcallee->flg & PROC_ISLIB)) || ( pbb->liveOut.any() ))
  329. {
  330. switch (pcallee->retVal.type) {
  331. case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
  332. ticode.du1.setDef(rAX).addDef(rDX);
  333. //TODO: use Calling convention to properly set regs here
  334. break;
  335. case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
  336. case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
  337. ticode.du1.setDef(rAX);
  338. break;
  339. default:
  340. ticode.du1 = ICODE::DU1(); // was .numRegsDef = 0
  341. //fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type);
  342. } /*eos*/
  343. /* Propagate def/use results to calling icode */
  344. ticode.du.use = pcallee->liveIn;
  345. ticode.du.def = pcallee->liveOut;
  346. }
  347. }
  348. }
  349. /* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */
  350. pbb->liveIn = LivenessSet(pbb->liveUse + (pbb->liveOut - pbb->def));
  351. /* Check if live sets have been modified */
  352. if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut))
  353. change = true;
  354. }
  355. }
  356. BB *pbb = m_dfsLast.front();
  357. /* Propagate liveIn(b) to procedure header */
  358. if (pbb->liveIn.any()) /* uses registers */
  359. liveIn = pbb->liveIn;
  360. /* Remove any references to register variables */
  361. if (flg & SI_REGVAR)
  362. {
  363. liveIn.clrReg(rSI);
  364. pbb->liveIn.clrReg(rSI);
  365. }
  366. if (flg & DI_REGVAR)
  367. {
  368. liveIn.clrReg(rDI);
  369. pbb->liveIn.clrReg(rDI);
  370. }
  371. }
  372. /* Check remaining instructions of the BB for all uses
  373. * of register regi, before any definitions of the
  374. * register */
  375. bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
  376. {
  377. if ((regi == rDI) && (flg & DI_REGVAR))
  378. return true;
  379. if ((regi == rSI) && (flg & SI_REGVAR))
  380. return true;
  381. if (distance(start_at,end())>1) /* several instructions */
  382. {
  383. iICODE ticode=end();
  384. // Only check uses of HIGH_LEVEL icodes
  385. auto hl_range=make_iterator_range(start_at,end()) | filtered(ICODE::select_high_level);
  386. auto checked_icode=hl_range.begin();
  387. ++checked_icode;
  388. for (; checked_icode != hl_range.end(); ++checked_icode)
  389. {
  390. ICODE &ic(*checked_icode);
  391. /* if used, get icode index */
  392. if ( ic.du.use.testRegAndSubregs(regi) )
  393. start_at->du1.recordUse(defRegIdx,checked_icode.base());
  394. /* if defined, stop finding uses for this reg */
  395. if (ic.du.def.testRegAndSubregs(regi))
  396. {
  397. ticode=checked_icode.base();
  398. break;
  399. }
  400. }
  401. if(ticode==end())
  402. ticode=(++riICODE(rbegin())).base();
  403. /* Check if last definition of this register */
  404. if (not ticode->du.def.testRegAndSubregs(regi) and liveOut.testRegAndSubregs(regi) )
  405. start_at->du.lastDefRegi.addReg(regi);
  406. }
  407. else /* only 1 instruction in this basic block */
  408. {
  409. /* Check if last definition of this register */
  410. if ( liveOut.testRegAndSubregs(regi) )
  411. start_at->du.lastDefRegi.addReg(regi);
  412. }
  413. return false;
  414. }
  415. /* Find target icode for HLI_CALL icodes to procedures
  416. * that are functions. The target icode is in the
  417. * next basic block (unoptimized code) or somewhere else
  418. * on optimized code. */
  419. void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
  420. {
  421. if (!((picode.hl()->opcode == HLI_CALL) && (picode.hl()->call.proc->flg & PROC_IS_FUNC)))
  422. return;
  423. BB *tbb = this->edges[0].BBptr;
  424. auto target_instructions = tbb->instructions | filtered(ICODE::select_high_level);
  425. for (auto iter=target_instructions.begin(); iter!=target_instructions.end(); ++iter)
  426. {
  427. /* if used, get icode index */
  428. if ( iter->du.use.testRegAndSubregs(regi) )
  429. picode.du1.recordUse(defRegIdx,iter.base());
  430. /* if defined, stop finding uses for this reg */
  431. if (iter->du.def.testRegAndSubregs(regi))
  432. break;
  433. }
  434. /* if not used in this basic block, check if the
  435. * register is live out, if so, make it the last
  436. * definition of this register */
  437. if ( picode.du1.used(defRegIdx) && tbb->liveOut.testRegAndSubregs(regi))
  438. picode.du.lastDefRegi.addReg(regi);
  439. }
  440. /* If not used within this bb or in successors of this
  441. * bb (ie. not in liveOut), then register is useless,
  442. * thus remove it. Also check that this is not a return
  443. * from a library function (routines such as printf
  444. * return an integer, which is normally not taken into
  445. * account by the programmer). */
  446. void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
  447. {
  448. if (picode->valid() and not picode->du1.used(defRegIdx) and
  449. (not picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
  450. (not ((picode->hl()->opcode == HLI_CALL) &&
  451. (picode->hl()->call.proc->flg & PROC_ISLIB))))
  452. {
  453. if (! (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */
  454. {
  455. bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId);
  456. if (res == true)
  457. {
  458. /* Backpatch any uses of this instruction, within
  459. * the same BB, if the instruction was invalidated */
  460. rICODE the_rest(begin(),picode);
  461. for ( ICODE &back_patch_at : the_rest|reversed)
  462. {
  463. back_patch_at.du1.remove(0,picode);
  464. }
  465. }
  466. }
  467. else /* liveOut */
  468. picode->du.lastDefRegi.addReg(regi);
  469. }
  470. }
  471. void BB::genDU1()
  472. {
  473. /* Process each register definition of a HIGH_LEVEL icode instruction.
  474. * Note that register variables should not be considered registers.
  475. */
  476. assert(nullptr!=Parent);
  477. auto all_high_levels = instructions | filtered(ICODE::select_high_level);
  478. for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode)
  479. {
  480. ICODE &ic = *picode;
  481. int defRegIdx = 0;
  482. // foreach defined register
  483. for (int k = rAX; k < INDEX_BX_SI; k++)
  484. {
  485. if (not ic.du.def.testReg(k))
  486. continue;
  487. eReg regi = (eReg)(k); /* Register that was defined */
  488. picode->du1.regi[defRegIdx] = regi;
  489. if(FindUseBeforeDef(regi,defRegIdx, picode.base()))
  490. continue;
  491. ProcessUseDefForFunc(regi, defRegIdx,ic);
  492. RemoveUnusedDefs(regi, defRegIdx, picode.base());
  493. defRegIdx++;
  494. /* Check if all defined registers have been processed */
  495. if ((defRegIdx >= picode->du1.getNumRegsDef()) || (defRegIdx == MAX_REGS_DEF))
  496. break;
  497. }
  498. }
  499. }
  500. /* Generates the du chain of each instruction in a basic block */
  501. void Function::genDU1 ()
  502. {
  503. /* Traverse tree in dfsLast order */
  504. assert(m_dfsLast.size()==numBBs);
  505. for(BB *pbb : m_dfsLast | filtered(BB::ValidFunctor()))
  506. {
  507. pbb->genDU1();
  508. }
  509. }
  510. /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the rhs of picode. */
  511. void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const
  512. {
  513. bool res;
  514. UnaryOperator *lhs_unary;
  515. while( (lhs_unary = dynamic_cast<UnaryOperator *>(lhs)) )
  516. {
  517. if(dynamic_cast<AstIdent *>(lhs_unary))
  518. break;
  519. lhs = lhs_unary->unaryExp;
  520. }
  521. RegisterNode * lhs_reg=dynamic_cast<RegisterNode *>(lhs_unary);
  522. assert(lhs_reg);
  523. if (rhs == nullptr) /* In case expression popped is NULL */
  524. return;
  525. /* Insert on rhs of ticode, if possible */
  526. res = Expr::insertSubTreeReg (ticode->hlU()->asgn.rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
  527. if (res)
  528. {
  529. picode->invalidate();
  530. numHlIcodes--;
  531. }
  532. else
  533. {
  534. /* Try to insert it on lhs of ticode*/
  535. RegisterNode *op = dynamic_cast<RegisterNode *>(ticode->hlU()->asgn.m_lhs);
  536. if(op)
  537. {
  538. eReg inserted = id_arr[lhs_reg->regiIdx].id.regi;
  539. eReg lhsReg = id_arr[op->regiIdx].id.regi;
  540. if((lhsReg==inserted)||Machine_X86::isSubRegisterOf(lhsReg,inserted))
  541. {
  542. // Do not replace ax = XYZ; given ax = H << P; with H << P =
  543. return;
  544. }
  545. }
  546. res = Expr::insertSubTreeReg (ticode->hlU()->asgn.m_lhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
  547. if (res)
  548. {
  549. picode->invalidate();
  550. numHlIcodes--;
  551. }
  552. }
  553. }
  554. /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the expression exp given */
  555. static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE ticode, int *numHlIcodes)
  556. {
  557. bool res;
  558. if (_exp == nullptr) /* In case expression popped is NULL */
  559. return;
  560. /* Insert on rhs of ticode, if possible */
  561. res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.rhs, longIdx);
  562. if (res)
  563. {
  564. picode->invalidate();
  565. (*numHlIcodes)--;
  566. }
  567. else
  568. {
  569. /* Try to insert it on lhs of ticode*/
  570. res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.m_lhs, longIdx);
  571. if (res)
  572. {
  573. picode->invalidate();
  574. (*numHlIcodes)--;
  575. }
  576. }
  577. }
  578. /* Returns whether the elements of the expression rhs are all x-clear from
  579. * instruction f up to instruction t. */
  580. bool UnaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs)
  581. {
  582. if(nullptr==unaryExp)
  583. return false;
  584. return unaryExp->xClear ( range_to_check, lastBBinst, locs);
  585. }
  586. bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs)
  587. {
  588. if(nullptr==m_rhs)
  589. return false;
  590. if ( ! m_rhs->xClear (range_to_check, lastBBinst, locs) )
  591. return false;
  592. if(nullptr==m_lhs)
  593. return false;
  594. return m_lhs->xClear (range_to_check, lastBBinst, locs);
  595. }
  596. bool AstIdent::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)
  597. {
  598. if (ident.idType != REGISTER)
  599. return true;
  600. assert(false);
  601. return false;
  602. }
  603. /** Checks the type of the formal argument as against to the actual argument,
  604. whenever possible, and then places the actual argument on the procedure's
  605. argument list.
  606. @returns the type size of the stored Arg
  607. */
  608. int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE * picode, size_t numArgs)
  609. {
  610. Expr *_exp;
  611. bool res;
  612. int size_of_arg=0;
  613. PROG &prog(Project::get()->prog);
  614. /* if (numArgs == 0)
  615. return; */
  616. assert(pProc==g_exp_stk.func);
  617. _exp = g_exp_stk.pop();
  618. if (callee->flg & PROC_ISLIB) /* library function */
  619. {
  620. if (callee->args.numArgs > 0)
  621. {
  622. if (callee->getFunctionType()->isVarArg())
  623. {
  624. if (numArgs < callee->args.size()) {
  625. if(_exp==nullptr)
  626. fprintf(stderr,"Would try to adjustForArgType with null _exp\n");
  627. else
  628. _exp = pProc->adjustActArgType (_exp, callee->args[numArgs].type);
  629. }
  630. }
  631. else {
  632. if(numArgs<callee->args.size()) {
  633. if(prog.addressingMode=='l') {
  634. if((callee->args[numArgs].type==TYPE_STR)||(callee->args[numArgs].type==TYPE_PTR)) {
  635. RegisterNode *rn = dynamic_cast<RegisterNode *>(g_exp_stk.top());
  636. AstIdent *idn = dynamic_cast<AstIdent *>(g_exp_stk.top());
  637. if(rn) {
  638. const ID &_id(pProc->localId.id_arr[rn->regiIdx]);
  639. assert(&pProc->localId==rn->m_syms);
  640. if(_id.id.regi==rDS) {
  641. g_exp_stk.pop(); // pop segment
  642. size_of_arg += 2;
  643. }
  644. } else if(idn) {
  645. Expr *tmp1 = new Constant(2,1);
  646. Expr *tmp2 = BinaryOperator::createSHL(_exp,tmp1);
  647. _exp = BinaryOperator::CreateAdd(g_exp_stk.top(),tmp2);
  648. g_exp_stk.pop(); // pop segment
  649. size_of_arg += 2;
  650. }
  651. }
  652. }
  653. _exp = pProc->adjustActArgType (_exp, callee->args[numArgs].type);
  654. } else {
  655. fprintf(stderr,"processCArg tried to query non existent arg\n");
  656. }
  657. }
  658. }
  659. }
  660. else /* user function */
  661. {
  662. if (callee->args.numArgs > 0)
  663. {
  664. if(_exp==nullptr)
  665. fprintf(stderr,"Would try to adjustForArgType with null _exp\n");
  666. else
  667. callee->args.adjustForArgType (numArgs, _exp->expType (pProc));
  668. }
  669. }
  670. res = picode->newStkArg (_exp, (llIcode)picode->ll()->getOpcode(), pProc);
  671. /* Do not update the size of k if the expression was a segment register
  672. * in a near call */
  673. if (res == false)
  674. {
  675. if(_exp==nullptr)
  676. return 2+size_of_arg;
  677. return _exp->hlTypeSize (pProc)+size_of_arg;
  678. }
  679. return 0; // be default we do not know the size of the argument
  680. }
  681. /** Eliminates extraneous intermediate icode instructions when finding
  682. * expressions. Generates new hlIcodes in the form of expression trees.
  683. * For HLI_CALL hlIcodes, places the arguments in the argument list. */
  684. void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode,bool isLong) const
  685. {
  686. bool res;
  687. HLTYPE &p_hl(*picode->hlU());
  688. HLTYPE &t_hl(*ticode->hlU());
  689. AstIdent *lhs_ident = dynamic_cast<AstIdent *>(p_hl.asgn.lhs());
  690. switch (t_hl.opcode)
  691. {
  692. case HLI_ASSIGN:
  693. assert(lhs_ident);
  694. if(isLong)
  695. {
  696. forwardSubsLong (lhs_ident->ident.idNode.longIdx,
  697. p_hl.asgn.rhs, picode,ticode,
  698. &numHlIcodes);
  699. }
  700. else
  701. this->forwardSubs (lhs_ident, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
  702. break;
  703. case HLI_JCOND: case HLI_PUSH: case HLI_RET:
  704. if(isLong)
  705. {
  706. assert(lhs_ident);
  707. res = Expr::insertSubTreeLongReg (
  708. p_hl.asgn.rhs,
  709. t_hl.exp.v,
  710. lhs_ident->ident.idNode.longIdx);
  711. }
  712. else
  713. {
  714. RegisterNode *lhs_reg = dynamic_cast<RegisterNode *>(p_hl.asgn.lhs());
  715. assert(lhs_reg);
  716. res = Expr::insertSubTreeReg (
  717. t_hl.exp.v,
  718. p_hl.asgn.rhs,
  719. id_arr[lhs_reg->regiIdx].id.regi,
  720. this);
  721. }
  722. if (res)
  723. {
  724. picode->invalidate();
  725. numHlIcodes--;
  726. }
  727. break;
  728. case HLI_CALL: /* register arguments */
  729. newRegArg ( picode, ticode);
  730. picode->invalidate();
  731. numHlIcodes--;
  732. break;
  733. default:
  734. fprintf(stderr,"unhandled LOCAL_ID::processTargetIcode opcode %d\n",t_hl.opcode);
  735. }
  736. }
  737. void C_CallingConvention::processHLI(Function *func,Expr *_exp, iICODE picode) {
  738. Function * pp;
  739. int cb, numArgs;
  740. int k;
  741. pp = picode->hl()->call.proc;
  742. cb = picode->hl()->call.args->cb;
  743. numArgs = 0;
  744. k = 0;
  745. if (cb)
  746. {
  747. while ( k < cb )
  748. {
  749. k+=processCArg (pp, func, &(*picode), numArgs);
  750. numArgs++;
  751. }
  752. }
  753. else if ((cb == 0) && picode->ll()->testFlags(REST_STK))
  754. {
  755. while (! g_exp_stk.empty())
  756. {
  757. k+=processCArg (pp, func, &(*picode), numArgs);
  758. numArgs++;
  759. }
  760. }
  761. }
  762. void Pascal_CallingConvention::processHLI(Function *func,Expr *_exp, iICODE picode) {
  763. Function * pp;
  764. int cb, numArgs;
  765. bool res;
  766. int k;
  767. pp = picode->hl()->call.proc;
  768. cb = pp->cbParam; /* fixed # arguments */
  769. k = 0;
  770. numArgs = 0;
  771. while(k<cb)
  772. {
  773. _exp = g_exp_stk.pop();
  774. if (pp->flg & PROC_ISLIB) /* library function */
  775. {
  776. if (pp->args.numArgs > 0)
  777. _exp = func->adjustActArgType(_exp, pp->args[numArgs].type);
  778. res = picode->newStkArg (_exp, (llIcode)picode->ll()->getOpcode(), func);
  779. }
  780. else /* user function */
  781. {
  782. if (pp->args.numArgs >0)
  783. {
  784. if(_exp==nullptr)
  785. {
  786. fprintf(stderr,"Would try to adjustForArgType with null _exp\n");
  787. }
  788. pp->args.adjustForArgType (numArgs,_exp->expType (func));
  789. }
  790. res = picode->newStkArg (_exp,(llIcode)picode->ll()->getOpcode(), func);
  791. }
  792. if (res == false)
  793. k += _exp->hlTypeSize (func);
  794. numArgs++;
  795. }
  796. }
  797. void Function::processHliCall(Expr *_exp, iICODE picode)
  798. {
  799. Function * pp = picode->hl()->call.proc;
  800. pp->callingConv()->processHLI(this,_exp,picode);
  801. }
  802. void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
  803. {
  804. bool res;
  805. ID *_retVal; // function return value
  806. Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL */
  807. //Expr *lhs; // exp ptr for return value of a HLI_CALL */
  808. iICODE ticode; // Target icode */
  809. HLTYPE *ti_hl=nullptr;
  810. uint8_t regi;
  811. numHlIcodes = 0;
  812. assert(&fnc->localId==&locals);
  813. // register(s) to be forward substituted */
  814. auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL>());
  815. for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++)
  816. {
  817. HLTYPE &_icHl(*picode->hlU());
  818. numHlIcodes++;
  819. if (picode->du1.getNumRegsDef() == 1) /* uint8_t/uint16_t regs */
  820. {
  821. /* Check for only one use of this register. If this is
  822. * the last definition of the register in this BB, check
  823. * that it is not liveOut from this basic block */
  824. if (picode->du1.numUses(0)==1)
  825. {
  826. /* Check that this register is not liveOut, if it
  827. * is the last definition of the register */
  828. regi = picode->du1.regi[0];
  829. /* Check if we can forward substitute this register */
  830. switch (_icHl.opcode)
  831. {
  832. case HLI_ASSIGN:
  833. /* Replace rhs of current icode into target
  834. * icode expression */
  835. ticode = picode->du1.idx[0].uses.front();
  836. if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
  837. ((ticode->hl()->opcode != HLI_CALL) &&
  838. (ticode->hl()->opcode != HLI_RET)))
  839. continue;
  840. if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
  841. end(), locals))
  842. {
  843. locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
  844. }
  845. break;
  846. case HLI_POP:
  847. // TODO: sometimes picode->du1.idx[0].uses.front() points to next basic block ?
  848. // pop X
  849. // lab1:
  850. // call F() <- somehow this is marked as user of POP ?
  851. ticode = picode->du1.idx[0].uses.front();
  852. ti_hl = ticode->hlU();
  853. if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
  854. ((ti_hl->opcode != HLI_CALL) &&
  855. (ti_hl->opcode != HLI_RET)))
  856. continue;
  857. _exp = g_exp_stk.pop(); /* pop last exp pushed */
  858. switch (ticode->hl()->opcode) {
  859. case HLI_ASSIGN:
  860. locals.forwardSubs(_icHl.expr(), _exp, picode.base(), ticode, numHlIcodes);
  861. break;
  862. case HLI_JCOND: case HLI_PUSH: case HLI_RET:
  863. {
  864. RegisterNode *v = dynamic_cast<RegisterNode *>(_icHl.expr());
  865. assert(v);
  866. res = Expr::insertSubTreeReg (ti_hl->exp.v,
  867. _exp,
  868. locals.id_arr[v->regiIdx].id.regi,
  869. &locals);
  870. if (res)
  871. {
  872. picode->invalidate();
  873. numHlIcodes--;
  874. }
  875. }
  876. break;
  877. /****case HLI_CALL: // register arguments
  878. newRegArg (pProc, picode, ticode);
  879. picode->invalidate();
  880. numHlIcodes--;
  881. break; */
  882. default:
  883. fprintf(stderr,"unhandled BB::findBBExps target opcode %d\n",ticode->hl()->opcode);
  884. } // eos
  885. break;
  886. case HLI_CALL:
  887. ticode = picode->du1.idx[0].uses.front();
  888. ti_hl = ticode->hlU();
  889. _retVal = &_icHl.call.proc->retVal;
  890. switch (ti_hl->opcode)
  891. {
  892. case HLI_ASSIGN:
  893. assert(ti_hl->asgn.rhs);
  894. _exp = _icHl.call.toAst();
  895. res = Expr::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals);
  896. if (! res)
  897. Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
  898. //TODO: HERE missing: 2 regs
  899. picode->invalidate();
  900. numHlIcodes--;
  901. break;
  902. case HLI_PUSH: case HLI_RET:
  903. ti_hl->expr( _icHl.call.toAst() );
  904. picode->invalidate();
  905. numHlIcodes--;
  906. break;
  907. case HLI_JCOND:
  908. _exp = _icHl.call.toAst();
  909. res = Expr::insertSubTreeReg (ti_hl->exp.v, _exp, _retVal->id.regi, &locals);
  910. if (res) /* was substituted */
  911. {
  912. picode->invalidate();
  913. numHlIcodes--;
  914. }
  915. else /* cannot substitute function */
  916. {
  917. auto lhs = AstIdent::idID(_retVal,&locals,picode.base());
  918. picode->setAsgn(lhs, _exp);
  919. }
  920. break;
  921. default:
  922. fprintf(stderr,"unhandled BB::findBBExps HLI_CALL target opcode %d\n",ti_hl->opcode);
  923. } /* eos */
  924. break;
  925. default:
  926. fprintf(stderr,"BB::findBBExps Unhandled HLI %d\n",_icHl.opcode);
  927. } /* eos */
  928. }
  929. }
  930. else if (picode->du1.getNumRegsDef() == 2) /* long regs */
  931. {
  932. /* Check for only one use of these registers */
  933. if ((picode->du1.numUses(0) == 1) and (picode->du1.numUses(1) == 1))
  934. {
  935. regi = picode->du1.regi[0]; //TODO: verify that regi actually should be assigned this
  936. switch (_icHl.opcode)
  937. {
  938. case HLI_ASSIGN:
  939. /* Replace rhs of current icode into target
  940. * icode expression */
  941. if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
  942. {
  943. ticode = picode->du1.idx[0].uses.front();
  944. if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
  945. ((ticode->hl()->opcode != HLI_CALL) &&
  946. (ticode->hl()->opcode != HLI_RET)))
  947. continue;
  948. locals.processTargetIcode(picode.base(), numHlIcodes, ticode,true);
  949. }
  950. break;
  951. case HLI_POP:
  952. if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
  953. {
  954. ticode = picode->du1.idx[0].uses.front();
  955. if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
  956. ((ticode->hl()->opcode != HLI_CALL) &&
  957. (ticode->hl()->opcode != HLI_RET)))
  958. continue;
  959. _exp = g_exp_stk.pop(); /* pop last exp pushed */
  960. switch (ticode->hl()->opcode) {
  961. case HLI_ASSIGN:
  962. forwardSubsLong (dynamic_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
  963. _exp, picode.base(), ticode, &numHlIcodes);
  964. break;
  965. case HLI_JCOND: case HLI_PUSH:
  966. res = Expr::insertSubTreeLongReg (_exp,
  967. ticode->hlU()->exp.v,
  968. dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
  969. if (res)
  970. {
  971. picode->invalidate();
  972. numHlIcodes--;
  973. }
  974. break;
  975. case HLI_CALL: /*** missing ***/
  976. break;
  977. default:
  978. fprintf(stderr,"BB::findBBExps Unhandled target op %d\n",ticode->hl()->opcode);
  979. } /* eos */
  980. }
  981. break;
  982. case HLI_CALL: /* check for function return */
  983. ticode = picode->du1.idx[0].uses.front();
  984. switch (ticode->hl()->opcode)
  985. {
  986. case HLI_ASSIGN:
  987. _exp = _icHl.call.toAst();
  988. ticode->hlU()->asgn.lhs(
  989. AstIdent::Long(&locals, DST,
  990. ticode,HIGH_FIRST, picode.base(),
  991. eDEF, *(++iICODE(ticode))->ll()));
  992. ticode->hlU()->asgn.rhs = _exp;
  993. picode->invalidate();
  994. numHlIcodes--;
  995. break;
  996. case HLI_PUSH:
  997. case HLI_RET:
  998. ticode->hlU()->expr( _icHl.call.toAst() );
  999. picode->invalidate();
  1000. numHlIcodes--;
  1001. break;
  1002. case HLI_JCOND:
  1003. _exp = _icHl.call.toAst();
  1004. _retVal = &picode->hl()->call.proc->retVal;
  1005. res = Expr::insertSubTreeLongReg (_exp,
  1006. ticode->hlU()->exp.v,
  1007. locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base()));
  1008. if (res) /* was substituted */
  1009. {
  1010. picode->invalidate();
  1011. numHlIcodes--;
  1012. }
  1013. else /* cannot substitute function */
  1014. {
  1015. auto lhs = locals.createId(_retVal,picode.base());
  1016. picode->setAsgn(lhs, _exp);
  1017. }
  1018. break;
  1019. default:
  1020. fprintf(stderr,"BB::findBBExps Unhandled target op %d\n",ticode->hl()->opcode);
  1021. } /* eos */
  1022. break;
  1023. default:
  1024. fprintf(stderr,"BB::findBBExps Unhandled HLI %d\n",_icHl.opcode);
  1025. } /* eos */
  1026. }
  1027. }
  1028. /* HLI_PUSH doesn't define any registers, only uses registers.
  1029. * Push the associated expression to the register on the local
  1030. * expression stack */
  1031. else if (_icHl.opcode == HLI_PUSH)
  1032. {
  1033. g_exp_stk.processExpPush(numHlIcodes, *picode);
  1034. }
  1035. else if(picode->du1.getNumRegsDef()!=0)
  1036. printf("Num def %d\n",picode->du1.getNumRegsDef());
  1037. /* For HLI_CALL instructions that use arguments from the stack,
  1038. * pop them from the expression stack and place them on the
  1039. * procedure's argument list */
  1040. if(_icHl.opcode == HLI_CALL)
  1041. {
  1042. if ( not _icHl.call.proc->hasRegArgs())
  1043. {
  1044. fnc->processHliCall(_exp, picode.base());
  1045. }
  1046. /* If we could not substitute the result of a function,
  1047. * assign it to the corresponding registers */
  1048. if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0))
  1049. {
  1050. _exp = new FuncNode(_icHl.call.proc, _icHl.call.args);
  1051. auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base());
  1052. picode->setAsgn(lhs, _exp);
  1053. }
  1054. }
  1055. }
  1056. /* Store number of high-level icodes in current basic block */
  1057. }
  1058. void Function::findExps()
  1059. {
  1060. /* Initialize expression stack */
  1061. g_exp_stk.init(this);
  1062. /* Traverse tree in dfsLast order */
  1063. for(BB *pbb : m_dfsLast | filtered(BB::ValidFunctor()))
  1064. {
  1065. /* Process one valid BB */
  1066. pbb->findBBExps( this->localId, this);
  1067. }
  1068. }
  1069. void Function::preprocessReturnDU(LivenessSet &_liveOut)
  1070. {
  1071. if (_liveOut.any())
  1072. {
  1073. // int idx;
  1074. bool isAx, isBx, isCx, isDx;
  1075. eReg bad_regs[] = {rES,rCS,rDS,rSS};
  1076. constexpr const char * names[] ={"ES","CS","DS","SS"};
  1077. for(int i=0; i<4; ++i)
  1078. if(_liveOut.testReg(bad_regs[i]))
  1079. {
  1080. fprintf(stderr,"LivenessSet probably screwed up, %s register as an liveOut in preprocessReturnDU\n",names[i]);
  1081. _liveOut.clrReg(bad_regs[i]);
  1082. if(not _liveOut.any())
  1083. return;
  1084. }
  1085. flg |= PROC_IS_FUNC;
  1086. isAx = _liveOut.testReg(rAX);
  1087. isBx = _liveOut.testReg(rBX);
  1088. isCx = _liveOut.testReg(rCX);
  1089. isDx = _liveOut.testReg(rDX);
  1090. bool isAL = !isAx && _liveOut.testReg(rAL);
  1091. bool isAH = !isAx && _liveOut.testReg(rAH);
  1092. bool isBL = !isBx && _liveOut.testReg(rBL);
  1093. bool isBH = !isBx && _liveOut.testReg(rBH);
  1094. bool isCL = !isCx && _liveOut.testReg(rCL);
  1095. bool isCH = !isCx && _liveOut.testReg(rCH);
  1096. bool isDL = !isDx && _liveOut.testReg(rDL);
  1097. bool isDH = !isDx && _liveOut.testReg(rDH);
  1098. if(isAL && isAH)
  1099. {
  1100. isAx = true;
  1101. isAH=isAL=false;
  1102. }
  1103. if(isDL && isDH)
  1104. {
  1105. isDx = true;
  1106. isDH=isDL=false;
  1107. }
  1108. if(isBL && isBH)
  1109. {
  1110. isBx = true;
  1111. isBH=isBL=false;
  1112. }
  1113. if(isCL && isCH)
  1114. {
  1115. isCx = true;
  1116. isCH=isCL=false;
  1117. }
  1118. if (isAx && isDx) /* long or pointer */
  1119. {
  1120. retVal.type = TYPE_LONG_SIGN;
  1121. retVal.loc = REG_FRAME;
  1122. retVal.longId() = LONGID_TYPE(rDX,rAX);
  1123. /*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin());
  1124. localId.propLongId (rAX, rDX, "\0");
  1125. }
  1126. else if (isAx || isBx || isCx || isDx) /* uint16_t */
  1127. {
  1128. retVal.type = TYPE_WORD_SIGN;
  1129. retVal.loc = REG_FRAME;
  1130. if (isAx)
  1131. retVal.id.regi = rAX;
  1132. else if (isBx)
  1133. retVal.id.regi = rBX;
  1134. else if (isCx)
  1135. retVal.id.regi = rCX;
  1136. else
  1137. retVal.id.regi = rDX;
  1138. /*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi);
  1139. }
  1140. else if(isAL||isBL||isCL||isDL)
  1141. {
  1142. retVal.type = TYPE_BYTE_SIGN;
  1143. retVal.loc = REG_FRAME;
  1144. if (isAL)
  1145. retVal.id.regi = rAL;
  1146. else if (isBL)
  1147. retVal.id.regi = rBL;
  1148. else if (isCL)
  1149. retVal.id.regi = rCL;
  1150. else
  1151. retVal.id.regi = rDL;
  1152. /*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
  1153. }
  1154. else if(isAH||isBH||isCH||isDH)
  1155. {
  1156. retVal.type = TYPE_BYTE_SIGN;
  1157. retVal.loc = REG_FRAME;
  1158. if (isAH)
  1159. retVal.id.regi = rAH;
  1160. else if (isBH)
  1161. retVal.id.regi = rBH;
  1162. else if (isCH)
  1163. retVal.id.regi = rCH;
  1164. else
  1165. retVal.id.regi = rDH;
  1166. /*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
  1167. }
  1168. }
  1169. }
  1170. /** Invokes procedures related with data flow analysis.
  1171. * Works on a procedure at a time basis.
  1172. \note indirect recursion in liveRegAnalysis is possible. */
  1173. void Function::dataFlow(LivenessSet &_liveOut)
  1174. {
  1175. /* Remove references to register variables */
  1176. if (flg & SI_REGVAR)
  1177. _liveOut.clrReg(rSI);
  1178. if (flg & DI_REGVAR)
  1179. _liveOut.clrReg(rDI);
  1180. /* Function - return value register(s) */
  1181. preprocessReturnDU(_liveOut);
  1182. /* Data flow analysis */
  1183. liveAnal = true;
  1184. elimCondCodes();
  1185. genLiveKtes();
  1186. liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */
  1187. if (! (flg & PROC_ASM)) /* can generate C for pProc */
  1188. {
  1189. genDU1 (); /* generate def/use level 1 chain */
  1190. findExps (); /* forward substitution algorithm */
  1191. }
  1192. }