dataflow.cpp 46 KB

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