hlicode.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /*
  2. * File: hlIcode.c
  3. * Purpose: High-level icode routines
  4. * Date: September-October 1993
  5. * (C) Cristina Cifuentes
  6. */
  7. #include "dcc.h"
  8. #include <QtCore/QDebug>
  9. #include <QtCore/QString>
  10. #include <cassert>
  11. #include <string.h>
  12. #include <string>
  13. #include <sstream>
  14. using namespace std;
  15. /* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
  16. void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
  17. {
  18. assert(lhs);
  19. set(lhs,rhs);
  20. }
  21. void ICODE::checkHlCall()
  22. {
  23. //assert((ll()->immed.proc.cb != 0) or ll()->immed.proc.proc!=0);
  24. }
  25. /* Places the new HLI_CALL high-level operand in the high-level icode array */
  26. void ICODE::newCallHl()
  27. {
  28. type = HIGH_LEVEL_ICODE;
  29. hlU()->setCall(ll()->src().proc.proc);
  30. if (ll()->src().proc.cb != 0)
  31. hlU()->call.args->cb = ll()->src().proc.cb;
  32. else if(hl()->call.proc)
  33. hlU()->call.args->cb = hl()->call.proc->cbParam;
  34. else
  35. {
  36. printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
  37. hl()->call.args->cb = 0;
  38. }
  39. }
  40. /* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
  41. * array */
  42. void ICODE::setUnary(hlIcode op, Expr *_exp)
  43. {
  44. type = HIGH_LEVEL_ICODE;
  45. hlU()->set(op,_exp);
  46. }
  47. /* Places the new HLI_JCOND high-level operand in the high-level icode array */
  48. void ICODE::setJCond(Expr *cexp)
  49. {
  50. type = HIGH_LEVEL_ICODE;
  51. hlU()->set(HLI_JCOND,cexp);
  52. }
  53. /* Sets the invalid field to true as this low-level icode is no longer valid,
  54. * it has been replaced by a high-level icode. */
  55. void ICODE ::invalidate()
  56. {
  57. invalid = true;
  58. }
  59. /* Removes the defined register regi from the lhs subtree.
  60. * If all registers
  61. * of this instruction are unused, the instruction is invalidated (ie. removed)
  62. */
  63. bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
  64. {
  65. int numDefs;
  66. numDefs = du1.getNumRegsDef();
  67. if (numDefs == thisDefIdx)
  68. {
  69. for ( ; numDefs > 0; numDefs--)
  70. {
  71. if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
  72. break;
  73. }
  74. }
  75. if (numDefs == 0)
  76. {
  77. invalidate();
  78. return true;
  79. }
  80. HlTypeSupport *p=hlU()->get();
  81. if(p and p->removeRegFromLong(regi,locId))
  82. {
  83. du1.removeDef(regi); //du1.numRegsDef--;
  84. //du.def &= maskDuReg[regi];
  85. du.def.clrReg(regi);
  86. }
  87. return false;
  88. }
  89. HLTYPE LLInst::createCall()
  90. {
  91. HLTYPE res(HLI_CALL);
  92. res.call.proc = src().proc.proc;
  93. res.call.args = new STKFRAME;
  94. if (src().proc.cb != 0)
  95. res.call.args->cb = src().proc.cb;
  96. else if(res.call.proc)
  97. res.call.args->cb =res.call.proc->cbParam;
  98. else
  99. {
  100. printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
  101. res.call.args->cb = 0;
  102. }
  103. return res;
  104. }
  105. #if 0
  106. HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
  107. {
  108. HLTYPE res(HLI_INVALID);
  109. if ( testFlags(NOT_HLL) )
  110. return res;
  111. flg = getFlag();
  112. switch (getOpcode())
  113. {
  114. case iADD:
  115. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  116. res.setAsgn(lhs, rhs);
  117. break;
  118. case iAND:
  119. rhs = COND_EXPR::boolOp (lhs, rhs, AND);
  120. res.setAsgn(lhs, rhs);
  121. break;
  122. case iCALL:
  123. case iCALLF:
  124. //TODO: this is noop pIcode->checkHlCall();
  125. res=createCall();
  126. break;
  127. case iDEC:
  128. rhs = AstIdent::idKte (1, 2);
  129. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  130. res.setAsgn(lhs, rhs);
  131. break;
  132. case iDIV:
  133. case iIDIV:/* should be signed div */
  134. rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
  135. if ( ll->testFlags(B) )
  136. {
  137. lhs = AstIdent::idReg (rAL, 0, &localId);
  138. pIcode->setRegDU( rAL, eDEF);
  139. }
  140. else
  141. {
  142. lhs = AstIdent::idReg (rAX, 0, &localId);
  143. pIcode->setRegDU( rAX, eDEF);
  144. }
  145. res.setAsgn(lhs, rhs);
  146. break;
  147. case iIMUL:
  148. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  149. lhs = AstIdent::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
  150. res.setAsgn(lhs, rhs);
  151. break;
  152. case iINC:
  153. rhs = AstIdent::idKte (1, 2);
  154. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  155. res.setAsgn(lhs, rhs);
  156. break;
  157. case iLEA:
  158. rhs = COND_EXPR::unary (ADDRESSOF, rhs);
  159. res.setAsgn(lhs, rhs);
  160. break;
  161. case iMOD:
  162. rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
  163. if ( ll->testFlags(B) )
  164. {
  165. lhs = AstIdent::idReg (rAH, 0, &localId);
  166. pIcode->setRegDU( rAH, eDEF);
  167. }
  168. else
  169. {
  170. lhs = AstIdent::idReg (rDX, 0, &localId);
  171. pIcode->setRegDU( rDX, eDEF);
  172. }
  173. res.setAsgn(lhs, rhs);
  174. break;
  175. case iMOV: res.setAsgn(lhs, rhs);
  176. break;
  177. case iMUL:
  178. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  179. lhs = AstIdent::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
  180. res.setAsgn(lhs, rhs);
  181. break;
  182. case iNEG:
  183. rhs = COND_EXPR::unary (NEGATION, lhs);
  184. res.setAsgn(lhs, rhs);
  185. break;
  186. case iNOT:
  187. rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
  188. res.setAsgn(lhs, rhs);
  189. break;
  190. case iOR:
  191. rhs = COND_EXPR::boolOp (lhs, rhs, OR);
  192. res.setAsgn(lhs, rhs);
  193. break;
  194. case iPOP: res.set(HLI_POP, lhs);
  195. break;
  196. case iPUSH: res.set(HLI_PUSH, lhs);
  197. break;
  198. case iRET:
  199. case iRETF:
  200. res.set(HLI_RET, NULL);
  201. break;
  202. case iSHL:
  203. rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
  204. res.setAsgn(lhs, rhs);
  205. break;
  206. case iSAR: /* signed */
  207. case iSHR:
  208. rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
  209. res.setAsgn(lhs, rhs);
  210. break;
  211. case iSIGNEX:
  212. res.setAsgn(lhs, rhs);
  213. break;
  214. case iSUB:
  215. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  216. res.setAsgn(lhs, rhs);
  217. break;
  218. case iXCHG:
  219. break;
  220. case iXOR:
  221. rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
  222. res.setAsgn(lhs, rhs);
  223. break;
  224. }
  225. return res;
  226. }
  227. #endif
  228. static bool needsLhs(unsigned opc)
  229. {
  230. switch (opc)
  231. {
  232. case iCALL:
  233. case iCALLF:
  234. case iRET:
  235. case iRETF:
  236. default: return false;
  237. case iADD:
  238. case iAND:
  239. case iDEC:
  240. case iDIV:
  241. case iIDIV:/* should be signed div */
  242. case iIMUL:
  243. case iINC:
  244. case iLEA:
  245. case iMOD:
  246. case iMOV:
  247. case iMUL:
  248. case iNEG:
  249. case iNOT:
  250. case iOR:
  251. case iPOP:
  252. case iPUSH:
  253. case iSHL:
  254. case iSAR: /* signed */
  255. case iSHR:
  256. case iSIGNEX:
  257. case iSUB:
  258. case iXCHG:
  259. case iXOR:
  260. return true;
  261. }
  262. }
  263. /* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
  264. * Note: this process should be done before data flow analysis, which
  265. * refines the HIGH_LEVEL icodes. */
  266. void Function::highLevelGen()
  267. {
  268. size_t numIcode; /* number of icode instructions */
  269. iICODE pIcode; /* ptr to current icode node */
  270. Expr *rhs; /* left- and right-hand side of expression */
  271. uint32_t _flg; /* icode flags */
  272. numIcode = Icode.size();
  273. for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
  274. {
  275. Expr *lhs=nullptr;
  276. assert(numIcode==Icode.size());
  277. pIcode = i; //Icode.GetIcode(i)
  278. LLInst *ll = pIcode->ll();
  279. LLOperand *dst_ll = ll->get(DST);
  280. LLOperand *src_ll = ll->get(SRC);
  281. if ( ll->testFlags(NOT_HLL) )
  282. pIcode->invalidate();
  283. if ((pIcode->type != LOW_LEVEL_ICODE) or not pIcode->valid() )
  284. continue;
  285. _flg = ll->getFlag();
  286. if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
  287. if ( not ll->testFlags(NO_OPS) ) /* if there are opers */
  288. {
  289. if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
  290. rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
  291. if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
  292. lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
  293. }
  294. if(ll->getOpcode()==iPUSH) {
  295. if(ll->testFlags(I)) {
  296. lhs = new Constant(src_ll->opz,src_ll->byteWidth());
  297. }
  298. // lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
  299. }
  300. if(needsLhs(ll->getOpcode()))
  301. assert(lhs!=nullptr);
  302. switch (ll->getOpcode())
  303. {
  304. case iADD:
  305. rhs = new BinaryOperator(ADD,lhs, rhs);
  306. pIcode->setAsgn(lhs, rhs);
  307. break;
  308. case iAND:
  309. rhs = BinaryOperator::And(lhs, rhs);
  310. pIcode->setAsgn(lhs, rhs);
  311. break;
  312. case iCALL:
  313. case iCALLF:
  314. pIcode->type = HIGH_LEVEL_ICODE;
  315. pIcode->hl( ll->createCall() );
  316. break;
  317. case iDEC:
  318. rhs = new BinaryOperator(SUB,lhs, new Constant(1, 2));
  319. pIcode->setAsgn(lhs, rhs);
  320. break;
  321. case iDIV:
  322. case iIDIV:/* should be signed div */
  323. {
  324. eReg v = ( dst_ll->byteWidth()==1) ? rAL:rAX;
  325. rhs = new BinaryOperator(DIV,lhs, rhs);
  326. lhs = new RegisterNode(LLOperand(v, dst_ll->byteWidth()), &localId);
  327. pIcode->setRegDU( v, eDEF);
  328. pIcode->setAsgn(lhs, rhs);
  329. }
  330. break;
  331. case iIMUL:
  332. rhs = new BinaryOperator(MUL,lhs, rhs);
  333. lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
  334. pIcode->setAsgn(lhs, rhs);
  335. break;
  336. case iINC:
  337. rhs = new BinaryOperator(ADD,lhs, new Constant(1, 2));
  338. pIcode->setAsgn(lhs, rhs);
  339. break;
  340. case iLEA:
  341. rhs =UnaryOperator::Create(ADDRESSOF, rhs);
  342. pIcode->setAsgn(lhs, rhs);
  343. break;
  344. case iMOD:
  345. {
  346. rhs = new BinaryOperator(MOD,lhs, rhs);
  347. eReg lhs_reg = (dst_ll->byteWidth()==1) ? rAH : rDX;
  348. lhs = new RegisterNode(LLOperand(lhs_reg, dst_ll->byteWidth()), &localId);
  349. pIcode->setRegDU( lhs_reg, eDEF);
  350. pIcode->setAsgn(lhs, rhs);
  351. }
  352. break;
  353. case iMOV: pIcode->setAsgn(lhs, rhs);
  354. break;
  355. case iMUL:
  356. rhs = new BinaryOperator(MUL,lhs, rhs);
  357. lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
  358. pIcode->setAsgn(lhs, rhs);
  359. break;
  360. case iNEG:
  361. rhs = UnaryOperator::Create(NEGATION, lhs);
  362. pIcode->setAsgn(lhs, rhs);
  363. break;
  364. case iNOT:
  365. rhs = new BinaryOperator(NOT,nullptr, rhs); // TODO: change this to unary NOT ?
  366. pIcode->setAsgn(lhs, rhs);
  367. break;
  368. case iOR:
  369. rhs = new BinaryOperator(OR,lhs, rhs);
  370. pIcode->setAsgn(lhs, rhs);
  371. break;
  372. case iPOP:
  373. pIcode->setUnary(HLI_POP, lhs);
  374. break;
  375. case iPUSH:
  376. pIcode->setUnary(HLI_PUSH, lhs);
  377. break;
  378. case iRET:
  379. case iRETF: pIcode->setUnary(HLI_RET, nullptr);
  380. break;
  381. case iSHL:
  382. rhs = new BinaryOperator(SHL,lhs, rhs);
  383. pIcode->setAsgn(lhs, rhs);
  384. break;
  385. case iSAR: /* signed */
  386. case iSHR:
  387. rhs = new BinaryOperator(SHR,lhs, rhs); /* unsigned*/
  388. pIcode->setAsgn(lhs, rhs);
  389. break;
  390. case iSIGNEX: pIcode->setAsgn(lhs, rhs);
  391. break;
  392. case iSUB:
  393. rhs = new BinaryOperator(SUB,lhs, rhs);
  394. pIcode->setAsgn(lhs, rhs);
  395. break;
  396. case iXCHG:
  397. break;
  398. case iXOR:
  399. rhs = new BinaryOperator(XOR,lhs, rhs);
  400. pIcode->setAsgn(lhs, rhs);
  401. break;
  402. }
  403. }
  404. }
  405. /**
  406. \fn COND_EXPR::inverse
  407. Modifies the given conditional operator to its inverse. This is used
  408. in if..then[..else] statements, to reflect the condition that takes the
  409. then part.
  410. */
  411. /* Returns the string that represents the procedure call of tproc (ie. with
  412. * actual parameters) */
  413. QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
  414. {
  415. //string condExp;
  416. QString ostr;
  417. ostr+=tproc->name+" (";
  418. for(const STKSYM &sym : args)
  419. {
  420. if(sym.actual)
  421. ostr += sym.actual->walkCondExpr(this, numLoc);
  422. else
  423. ostr += "";
  424. if((&sym)!=&(args.back()))
  425. ostr += ", ";
  426. }
  427. ostr += ")";
  428. return ostr;
  429. }
  430. /* Displays the output of a HLI_JCOND icode. */
  431. QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
  432. {
  433. if(h.opcode==HLI_INVALID)
  434. {
  435. return "if (*HLI_INVALID*) {\n";
  436. }
  437. assert(h.expr());
  438. Expr *inverted=h.expr()->inverse();
  439. //inverseCondOp (&h.exp);
  440. QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
  441. delete inverted;
  442. return QString("if %1 {\n").arg(inverted_form);
  443. }
  444. /* Displays the inverse output of a HLI_JCOND icode. This is used in the case
  445. * when the THEN clause of an if..then..else is empty. The clause is
  446. * negated and the ELSE clause is used instead. */
  447. QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
  448. {
  449. QString _form;
  450. if(h.expr()==nullptr)
  451. _form = "( *failed condition recovery* )";
  452. else
  453. _form = h.expr()->walkCondExpr (pProc, numLoc);
  454. return QString("if %1 {\n").arg(_form);
  455. }
  456. QString AssignType::writeOut(Function *pProc, int *numLoc) const
  457. {
  458. return QString("%1 = %2;\n")
  459. .arg(m_lhs->walkCondExpr (pProc, numLoc))
  460. .arg(m_rhs->walkCondExpr (pProc, numLoc));
  461. }
  462. QString CallType::writeOut(Function *pProc, int *numLoc) const
  463. {
  464. return pProc->writeCall (proc, *args, numLoc) + ";\n";
  465. }
  466. QString ExpType::writeOut(Function *pProc, int *numLoc) const
  467. {
  468. if(v==nullptr)
  469. return "";
  470. return v->walkCondExpr (pProc, numLoc);
  471. }
  472. void HLTYPE::set(Expr *l, Expr *r)
  473. {
  474. assert(l);
  475. assert(r);
  476. opcode = HLI_ASSIGN;
  477. //assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
  478. assert(dynamic_cast<UnaryOperator *>(l));
  479. asgn.m_lhs=l;
  480. asgn.m_rhs=r;
  481. }
  482. /* Returns a string with the contents of the current high-level icode.
  483. * Note: this routine does not output the contens of HLI_JCOND icodes. This is
  484. * done in a separate routine to be able to support the removal of
  485. * empty THEN clauses on an if..then..else. */
  486. QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
  487. {
  488. const HlTypeSupport *p = get();
  489. switch (opcode)
  490. {
  491. case HLI_ASSIGN:
  492. return p->writeOut(pProc,numLoc);
  493. case HLI_CALL:
  494. return p->writeOut(pProc,numLoc);
  495. case HLI_RET:
  496. {
  497. QString e;
  498. e = p->writeOut(pProc,numLoc);
  499. if (not e.isEmpty())
  500. return QString("return (%1);\n").arg(e);
  501. break;
  502. }
  503. case HLI_POP:
  504. return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
  505. case HLI_PUSH:
  506. return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
  507. case HLI_JCOND: //Handled elsewhere
  508. break;
  509. default:
  510. qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
  511. }
  512. return "";
  513. }
  514. //TODO: replace all "< (INDEX_BX_SI-1)" with machine_x86::lastReg
  515. //TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression
  516. /* Writes the registers/stack variables that are used and defined by this
  517. * instruction. */
  518. void ICODE::writeDU()
  519. {
  520. int my_idx = loc_ip;
  521. {
  522. QString ostr_contents;
  523. {
  524. QTextStream ostr(&ostr_contents);
  525. Machine_X86::writeRegVector(ostr,du.def);
  526. }
  527. if (not ostr_contents.isEmpty())
  528. qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
  529. }
  530. {
  531. QString ostr_contents;
  532. {
  533. QTextStream ostr(&ostr_contents);
  534. Machine_X86::writeRegVector(ostr,du.use);
  535. }
  536. if (not ostr_contents.isEmpty())
  537. qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
  538. }
  539. /* Print du1 chain */
  540. printf ("# regs defined = %d\n", du1.getNumRegsDef());
  541. for (int i = 0; i < MAX_REGS_DEF; i++)
  542. {
  543. if (not du1.used(i))
  544. continue;
  545. printf ("%d: du1[%d][] = ", my_idx, i);
  546. for(auto j : du1.idx[i].uses)
  547. {
  548. printf ("%d ", j->loc_ip);
  549. }
  550. printf ("\n");
  551. }
  552. /* For HLI_CALL, print # parameter bytes */
  553. if (hl()->opcode == HLI_CALL)
  554. printf ("# param bytes = %d\n", hl()->call.args->cb);
  555. printf ("\n");
  556. }