dataflow.cpp 47 KB

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