hlicode.cpp 18 KB

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