hlicode.cpp 18 KB

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