axe_cflow_graph.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. /*
  2. * Andrea Di Biagio
  3. * Politecnico di Milano, 2007
  4. *
  5. * axe_cflow_graph.c
  6. * Formal Languages & Compilers Machine, 2007/2008
  7. *
  8. */
  9. #include <assert.h>
  10. #include "axe_labels.h"
  11. #include "axe_cflow_graph.h"
  12. #include "cflow_constants.h"
  13. #include "collections.h"
  14. #include "axe_debug.h"
  15. int cflow_errorcode;
  16. static t_cflow_var * allocVariable (t_cflow_Graph *graph, int identifier);
  17. static int isEndingNode(t_axe_instruction *instr);
  18. static int isStartingNode(t_axe_instruction *instr);
  19. static int isJumpInstruction(t_axe_instruction *instr);
  20. static int isUnconditionalJump(t_axe_instruction *instr);
  21. static int isHaltInstruction(t_axe_instruction *instr);
  22. static int isLoadInstruction(t_axe_instruction *instr);
  23. static void updateFlowGraph(t_cflow_Graph *graph);
  24. static t_basic_block * searchLabel(t_cflow_Graph *graph, t_axe_label *label);
  25. static void setDefUses(t_cflow_Graph *graph, t_cflow_Node *node);
  26. static int performLivenessIteration(t_cflow_Graph *graph);
  27. static int performLivenessOnBlock(t_basic_block *current_block, t_list *out);
  28. static t_list * addVariableToSet(t_list *set
  29. , t_cflow_var *element, int *modified);
  30. static int compare_CFLOW_Variables (void *a, void *b);
  31. static t_list * computeLiveOutVars(t_cflow_Graph *graph,t_basic_block *block);
  32. void performLivenessAnalysis(t_cflow_Graph *graph)
  33. {
  34. int modified;
  35. do
  36. {
  37. modified = performLivenessIteration(graph);
  38. }while(modified);
  39. }
  40. t_list * computeLiveOutVars(t_cflow_Graph *graph, t_basic_block *block)
  41. {
  42. t_list *current_elem;
  43. t_basic_block *current_succ;
  44. t_list *result;
  45. t_list *liveINVars;
  46. /* preconditions */
  47. if (block == NULL)
  48. return NULL;
  49. if (graph == NULL) {
  50. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  51. return NULL;
  52. }
  53. /* initialize `current_elem' */
  54. current_elem = block->succ;
  55. /* initialize `result' */
  56. result = NULL;
  57. while(current_elem != NULL)
  58. {
  59. current_succ = (t_basic_block *) LDATA(current_elem);
  60. assert(current_succ != NULL);
  61. if (current_succ != graph->endingBlock)
  62. {
  63. liveINVars = getLiveINVars(current_succ);
  64. /* update the value of `result' */
  65. result = addListToSet(result
  66. , liveINVars, NULL, NULL);
  67. /* free the temporary list of live intervals */
  68. freeList(liveINVars);
  69. }
  70. current_elem = LNEXT(current_elem);
  71. }
  72. /* postconditions */
  73. return result;
  74. }
  75. t_list * getLiveOUTVars(t_basic_block *bblock)
  76. {
  77. t_list *last_Element;
  78. t_cflow_Node *lastNode;
  79. if (bblock == NULL)
  80. return NULL;
  81. if (bblock->nodes == NULL)
  82. return NULL;
  83. last_Element = getLastElement(bblock->nodes);
  84. lastNode = (t_cflow_Node *) LDATA(last_Element);
  85. assert(lastNode != NULL);
  86. /* return a copy of the list of variables live in
  87. * input to the current basic block */
  88. return cloneList(lastNode->out);
  89. }
  90. t_list * getLiveINVars(t_basic_block *bblock)
  91. {
  92. t_cflow_Node *firstNode;
  93. if (bblock == NULL)
  94. return NULL;
  95. if (bblock->nodes == NULL)
  96. return NULL;
  97. firstNode = (t_cflow_Node *) LDATA(bblock->nodes);
  98. assert(firstNode != NULL);
  99. /* return a copy of the list of variables live in
  100. * input to the current basic block */
  101. return cloneList(firstNode->in);
  102. }
  103. t_list * addVariableToSet(t_list *set
  104. , t_cflow_var *element, int *modified)
  105. {
  106. /* test the preconditions */
  107. if (element == NULL)
  108. return set;
  109. if (CustomfindElement(set, element
  110. , compare_CFLOW_Variables) == NULL)
  111. {
  112. set = addElement(set, element, -1);
  113. if (modified != NULL)
  114. (* modified) = 1;
  115. }
  116. /* postconditions */
  117. return set;
  118. }
  119. t_list * addVariables(t_list *set, t_list *elements, int *modified)
  120. {
  121. /* test the preconditions */
  122. if (set == NULL || elements == NULL)
  123. return set;
  124. /* update the set of variables */
  125. set = addListToSet(set, elements
  126. , compare_CFLOW_Variables, modified);
  127. /* postconditions: return the new list of variables */
  128. return set;
  129. }
  130. int compare_CFLOW_Variables (void *a, void *b)
  131. {
  132. t_cflow_var *varA;
  133. t_cflow_var *varB;
  134. if (a == NULL)
  135. {
  136. if (b == NULL)
  137. return 1;
  138. return 0;
  139. }
  140. if (b == NULL)
  141. return 0;
  142. varA = (t_cflow_var *) a;
  143. varB = (t_cflow_var *) b;
  144. return (varA->ID == varB->ID);
  145. }
  146. int performLivenessOnBlock(t_basic_block *bblock, t_list *out)
  147. {
  148. t_list *current_element;
  149. t_list *cloned_list;
  150. t_cflow_Node *next_node;
  151. t_cflow_Node *current_node;
  152. int modified;
  153. /* initialize the local variables */
  154. modified = 0;
  155. if (bblock == NULL || bblock->nodes == NULL) {
  156. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  157. return modified;
  158. }
  159. current_element = getLastElement(bblock->nodes);
  160. current_node = (t_cflow_Node *) LDATA(current_element);
  161. assert(current_node != NULL);
  162. /* update the out set */
  163. current_node->out = addListToSet
  164. (current_node->out, out, NULL, &modified);
  165. /* update the in list */
  166. cloned_list = cloneList(current_node->out);
  167. #if CFLOW_ALWAYS_LIVEIN_R0 == (1)
  168. if ((current_node->uses)[0] != NULL && (current_node->uses)[0]->ID != REG_0)
  169. cloned_list = addVariableToSet
  170. (cloned_list, (current_node->uses)[0], NULL);
  171. if ((current_node->uses)[1] != NULL && (current_node->uses)[1]->ID != REG_0)
  172. cloned_list = addVariableToSet
  173. (cloned_list, (current_node->uses)[1], NULL);
  174. if ((current_node->uses)[2] != NULL && (current_node->uses)[2]->ID != REG_0)
  175. cloned_list = addVariableToSet
  176. (cloned_list, (current_node->uses)[2], NULL);
  177. #else
  178. if ((current_node->uses)[0] != NULL)
  179. cloned_list = addVariableToSet
  180. (cloned_list, (current_node->uses)[0], NULL);
  181. if ((current_node->uses)[1] != NULL)
  182. cloned_list = addVariableToSet
  183. (cloned_list, (current_node->uses)[1], NULL);
  184. if ((current_node->uses)[2] != NULL)
  185. cloned_list = addVariableToSet
  186. (cloned_list, (current_node->uses)[2], NULL);
  187. #endif
  188. #if CFLOW_ALWAYS_LIVEIN_R0 == (1)
  189. if (current_node->def != NULL && (current_node->def)->ID != REG_0)
  190. #else
  191. if (current_node->def != NULL)
  192. #endif
  193. {
  194. int found = 0;
  195. int current_use_idx = 0;
  196. do
  197. {
  198. if ((current_node->uses)[current_use_idx] != NULL)
  199. {
  200. if ((current_node->uses)[current_use_idx]->ID == current_node->def->ID)
  201. found = 1;
  202. }
  203. current_use_idx++;
  204. } while((found == 0) && (current_use_idx < 3));
  205. if (!found)
  206. cloned_list = removeElement(cloned_list, current_node->def);
  207. }
  208. current_node->in = addListToSet
  209. (current_node->in, cloned_list, NULL, &modified);
  210. /* remove the cloned list */
  211. freeList(cloned_list);
  212. /* set the new value of next_node */
  213. next_node = current_node;
  214. current_element = LPREV(current_element);
  215. while (current_element != NULL)
  216. {
  217. /* take a new node */
  218. current_node = (t_cflow_Node *) LDATA(current_element);
  219. assert(current_node != NULL);
  220. /* clone the `in' list of the next_node */
  221. cloned_list = cloneList(next_node->in);
  222. /* update the out list */
  223. current_node->out = addListToSet
  224. (current_node->out, cloned_list, NULL, &modified);
  225. /* remove the cloned list */
  226. freeList(cloned_list);
  227. /* clone the `in' list of the next_node */
  228. cloned_list = cloneList(current_node->out);
  229. /* update the in list */
  230. #if CFLOW_ALWAYS_LIVEIN_R0 == (1)
  231. if ((current_node->uses)[0] != NULL && (current_node->uses)[0]->ID != REG_0)
  232. cloned_list = addVariableToSet
  233. (cloned_list, (current_node->uses)[0], NULL);
  234. if ((current_node->uses)[1] != NULL && (current_node->uses)[1]->ID != REG_0)
  235. cloned_list = addVariableToSet
  236. (cloned_list, (current_node->uses)[1], NULL);
  237. if ((current_node->uses)[2] != NULL && (current_node->uses)[2]->ID != REG_0)
  238. cloned_list = addVariableToSet
  239. (cloned_list, (current_node->uses)[2], NULL);
  240. #else
  241. if ((current_node->uses)[0] != NULL)
  242. cloned_list = addVariableToSet
  243. (cloned_list, (current_node->uses)[0], NULL);
  244. if ((current_node->uses)[1] != NULL)
  245. cloned_list = addVariableToSet
  246. (cloned_list, (current_node->uses)[1], NULL);
  247. if ((current_node->uses)[2] != NULL)
  248. cloned_list = addVariableToSet
  249. (cloned_list, (current_node->uses)[2], NULL);
  250. #endif
  251. #if CFLOW_ALWAYS_LIVEIN_R0 == (1)
  252. if (current_node->def != NULL && (current_node->def)->ID != REG_0)
  253. #else
  254. if (current_node->def != NULL)
  255. #endif
  256. {
  257. int found = 0;
  258. int current_use_idx = 0;
  259. do
  260. {
  261. if ((current_node->uses)[current_use_idx] != NULL)
  262. {
  263. if ((current_node->uses)[current_use_idx]->ID
  264. == current_node->def->ID)
  265. {
  266. found = 1;
  267. }
  268. }
  269. current_use_idx++;
  270. } while((found == 0) && (current_use_idx < 3));
  271. if (!found)
  272. cloned_list = removeElement(cloned_list, current_node->def);
  273. }
  274. current_node->in = addListToSet
  275. (current_node->in, cloned_list, NULL, &modified);
  276. /* remove the cloned list */
  277. freeList(cloned_list);
  278. /* update the loop control informations */
  279. current_element = LPREV(current_element);
  280. next_node = current_node;
  281. }
  282. /* return the `modified' value */
  283. return modified;
  284. }
  285. static int isLoadInstruction(t_axe_instruction *instr)
  286. {
  287. if (instr == NULL) {
  288. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  289. return 0;
  290. }
  291. return (instr->opcode == LOAD) ? 1 : 0;
  292. }
  293. int isHaltInstruction(t_axe_instruction *instr)
  294. {
  295. if (instr == NULL) {
  296. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  297. return 0;
  298. }
  299. return (instr->opcode == HALT) ? 1 : 0;
  300. }
  301. int performLivenessIteration(t_cflow_Graph *graph)
  302. {
  303. int modified;
  304. t_list *current_element;
  305. t_basic_block *current_bblock;
  306. /* initialize the value of the local variable `modified' */
  307. modified = 0;
  308. /* test the preconditions */
  309. if (graph == NULL) {
  310. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  311. return modified;
  312. }
  313. /* test if `graph->endingBlock' is valid */
  314. if (graph->endingBlock == NULL) {
  315. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  316. return modified;
  317. }
  318. /* retrieve the last basic block in the list */
  319. current_element = getLastElement(graph->blocks);
  320. while(current_element != NULL)
  321. {
  322. t_list *live_out_vars;
  323. current_bblock = (t_basic_block *) LDATA(current_element);
  324. assert(current_bblock != NULL);
  325. /* retrieve the variables that will be live out from this block */
  326. live_out_vars = computeLiveOutVars(graph, current_bblock);
  327. /* test if an error occurred */
  328. if (cflow_errorcode != CFLOW_OK)
  329. return modified;
  330. /* retrieve the liveness informations for the current bblock */
  331. if (performLivenessOnBlock(current_bblock, live_out_vars))
  332. modified = 1;
  333. /* remove the list `out' */
  334. freeList(live_out_vars);
  335. /* test if an error occurred */
  336. if (cflow_errorcode != CFLOW_OK) {
  337. return modified;
  338. }
  339. /* retrieve the previous element in the list */
  340. current_element = LPREV(current_element);
  341. }
  342. /* return 1 if another liveness iteration is required */
  343. return modified;
  344. }
  345. /* alloc a variable identifier */
  346. t_cflow_var * allocVariable (t_cflow_Graph *graph, int identifier)
  347. {
  348. t_cflow_var * result;
  349. t_list *elementFound;
  350. if (graph == NULL)
  351. {
  352. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  353. return NULL;
  354. }
  355. /* alloc memory for a variable information */
  356. result = _AXE_ALLOC_FUNCTION(sizeof(t_cflow_var));
  357. if (result == NULL) {
  358. cflow_errorcode = CFLOW_OUT_OF_MEMORY;
  359. return NULL;
  360. }
  361. /* update the value of result */
  362. result->ID = identifier;
  363. /* test if a variable with the same identifier was already present */
  364. elementFound = CustomfindElement
  365. (graph->cflow_variables, result, compare_CFLOW_Variables);
  366. if (elementFound == NULL)
  367. {
  368. /* update the set of variables */
  369. graph->cflow_variables = addElement
  370. (graph->cflow_variables, result, -1);
  371. }
  372. else
  373. {
  374. _AXE_FREE_FUNCTION(result);
  375. result = (t_cflow_var *) LDATA(elementFound);
  376. assert(result != NULL);
  377. assert(result->ID == identifier);
  378. }
  379. /* return a new var identifier */
  380. return result;
  381. }
  382. /* set the def-use values for the current node */
  383. void setDefUses(t_cflow_Graph *graph, t_cflow_Node *node)
  384. {
  385. t_axe_instruction *instr;
  386. t_cflow_var *varDest;
  387. t_cflow_var *varSource1;
  388. t_cflow_var *varSource2;
  389. /* preconditions */
  390. if (graph == NULL) {
  391. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  392. return;
  393. }
  394. if (node == NULL) {
  395. cflow_errorcode = CFLOW_INVALID_NODE;
  396. return;
  397. }
  398. if (node->instr == NULL) {
  399. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  400. return;
  401. }
  402. if ((node->instr)->opcode == INVALID_OPCODE) {
  403. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  404. return;
  405. }
  406. /* update the value of `instr' */
  407. instr = node->instr;
  408. /* if the instruction is a Jump instruction then does nothing */
  409. if ( isJumpInstruction(instr))
  410. return;
  411. /* initialize the values of varDest, varSource1 and varSource2 */
  412. varDest = NULL;
  413. varSource1 = NULL;
  414. varSource2 = NULL;
  415. /* update the values of the variables */
  416. if (instr->reg_1 != NULL)
  417. varDest = allocVariable(graph, (instr->reg_1)->ID);
  418. if (instr->reg_2 != NULL)
  419. varSource1 = allocVariable(graph, (instr->reg_2)->ID);
  420. if (instr->reg_3 != NULL)
  421. varSource2 = allocVariable(graph, (instr->reg_3)->ID);
  422. switch(instr->opcode)
  423. {
  424. case LOAD : case AXE_READ : node->def = varDest; break;
  425. case STORE : case AXE_WRITE : (node->uses)[0] = varDest; break;
  426. case SGE : case SGT: case SLE : case SLT : case SNE :
  427. case SEQ : node->def = varDest; break;
  428. case HALT : case RET : case JSR : case NOP : break;
  429. case MOVA : node->def = varDest; break;
  430. case NOTB : case NOTL : case ROTRI : case ROTLI :
  431. case SHRI : case SHLI : case DIVI : case MULI :
  432. case EORBI : case ORBI : case ANDBI : case EORLI :
  433. case ORLI : case ANDLI : case SUBI : case ADDI :
  434. node->def = varDest;
  435. (node->uses)[0] = varSource1; break;
  436. default :
  437. if ((instr->reg_1)->indirect)
  438. (node->uses)[2] = varDest;
  439. else
  440. node->def = varDest;
  441. (node->uses)[0] = varSource1;
  442. (node->uses)[1] = varSource2;
  443. }
  444. }
  445. /* test if the current instruction `instr' is a BT or a BF */
  446. int isUnconditionalJump(t_axe_instruction *instr)
  447. {
  448. if (isJumpInstruction(instr))
  449. {
  450. if ((instr->opcode == BT) || (instr->opcode == BF))
  451. return 1;
  452. }
  453. return 0;
  454. }
  455. /* test if the current instruction `instr' is a branch instruction */
  456. int isJumpInstruction(t_axe_instruction *instr)
  457. {
  458. if (instr == NULL)
  459. return 0;
  460. switch(instr->opcode)
  461. {
  462. case BT :
  463. case BF :
  464. case BHI :
  465. case BLS :
  466. case BCC :
  467. case BCS :
  468. case BNE :
  469. case BEQ :
  470. case BVC :
  471. case BVS :
  472. case BPL :
  473. case BMI :
  474. case BGE :
  475. case BLT :
  476. case BGT :
  477. case BLE : return 1;
  478. default : return 0;
  479. }
  480. }
  481. /* look up for a label inside the graph */
  482. t_basic_block * searchLabel(t_cflow_Graph *graph, t_axe_label *label)
  483. {
  484. t_list *current_element;
  485. t_basic_block *bblock;
  486. t_cflow_Node *current_node;
  487. /* preconditions: graph should not be a NULL pointer */
  488. if (graph == NULL){
  489. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  490. return NULL;
  491. }
  492. /* test if we haven't to search for a label */
  493. if (label == NULL)
  494. return NULL;
  495. /* initialize `bblock' */
  496. bblock = NULL;
  497. current_element = graph->blocks;
  498. while(current_element != NULL)
  499. {
  500. bblock = (t_basic_block *) LDATA(current_element);
  501. assert(bblock != NULL);
  502. assert(bblock->nodes != NULL);
  503. /* retrieve the first node of the basic block */
  504. current_node = (t_cflow_Node *) LDATA(bblock->nodes);
  505. assert(current_node != NULL);
  506. /* if the first node holds a label information, we
  507. * have to verify if we have found the right label */
  508. if ((current_node->instr)->labelID != NULL)
  509. {
  510. if (compareLabels((current_node->instr)->labelID, label))
  511. /* we found the correct basic block */
  512. break;
  513. }
  514. /* retrieve the next element */
  515. current_element = LNEXT(current_element);
  516. }
  517. return bblock;
  518. }
  519. /* test if the current instruction `instr' is a labelled instruction */
  520. int isStartingNode(t_axe_instruction *instr)
  521. {
  522. /* preconditions */
  523. if ((instr == NULL) || (instr->opcode == INVALID_OPCODE))
  524. {
  525. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  526. return 0;
  527. }
  528. /* test if the instruction holds a label identifier */
  529. if (instr->labelID != NULL)
  530. {
  531. if ((instr->labelID)->labelID == LABEL_UNSPECIFIED)
  532. {
  533. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  534. return 0;
  535. }
  536. return 1;
  537. }
  538. return 0;
  539. }
  540. /* test if the current instruction will end a basic block */
  541. int isEndingNode(t_axe_instruction *instr)
  542. {
  543. /* preconditions */
  544. if ((instr == NULL) || (instr->opcode == INVALID_OPCODE))
  545. {
  546. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  547. return 0;
  548. }
  549. switch (instr->opcode)
  550. {
  551. case JSR :
  552. case RET :
  553. case HALT:
  554. case BT :
  555. case BF :
  556. case BHI :
  557. case BLS :
  558. case BCC :
  559. case BCS :
  560. case BNE :
  561. case BEQ :
  562. case BVC :
  563. case BVS :
  564. case BPL :
  565. case BMI :
  566. case BGE :
  567. case BLT :
  568. case BGT :
  569. case BLE : return 1;
  570. default : return 0;
  571. }
  572. }
  573. /* allocate memory for a control flow graph */
  574. t_cflow_Graph * allocGraph()
  575. {
  576. t_cflow_Graph *result;
  577. result = _AXE_ALLOC_FUNCTION(sizeof(t_cflow_Graph));
  578. if (result == NULL) {
  579. cflow_errorcode = CFLOW_OUT_OF_MEMORY;
  580. return NULL;
  581. }
  582. /* initialize `result' */
  583. result->startingBlock = NULL;
  584. result->blocks = NULL;
  585. result->cflow_variables = NULL;
  586. result->endingBlock = allocBasicBlock();
  587. /* test if an error occurred */
  588. if (result->endingBlock == NULL) {
  589. cflow_errorcode = CFLOW_OUT_OF_MEMORY;
  590. _AXE_FREE_FUNCTION(result);
  591. return NULL;
  592. }
  593. /* return the just created cflow graph */
  594. return result;
  595. }
  596. /* finalize the memory associated with the given control flow graph */
  597. void finalizeGraph(t_cflow_Graph *graph)
  598. {
  599. t_list *current_element;
  600. t_basic_block *current_block;
  601. if (graph == NULL)
  602. return;
  603. current_element = graph->blocks;
  604. while (current_element != NULL)
  605. {
  606. /* retrieve the current node */
  607. current_block = (t_basic_block *) LDATA(current_element);
  608. assert(current_block != NULL);
  609. finalizeBasicBlock(current_block);
  610. current_element = LNEXT(current_element);
  611. }
  612. if (graph->blocks != NULL)
  613. freeList(graph->blocks);
  614. if (graph->endingBlock != NULL)
  615. finalizeBasicBlock(graph->endingBlock);
  616. if (graph->cflow_variables != NULL)
  617. {
  618. t_list *current_element;
  619. t_cflow_var *current_variable;
  620. current_element = graph->cflow_variables;
  621. while (current_element != NULL)
  622. {
  623. current_variable = (t_cflow_var *) LDATA(current_element);
  624. if (current_variable != NULL)
  625. _AXE_FREE_FUNCTION(current_variable);
  626. /* retrieve the next variable in the list */
  627. current_element = LNEXT(current_element);
  628. }
  629. freeList(graph->cflow_variables);
  630. }
  631. _AXE_FREE_FUNCTION(graph);
  632. }
  633. /* allocate memory for a basic block */
  634. t_basic_block * allocBasicBlock()
  635. {
  636. t_basic_block *result;
  637. result = _AXE_ALLOC_FUNCTION(sizeof(t_basic_block));
  638. if (result == NULL)
  639. {
  640. cflow_errorcode = CFLOW_OUT_OF_MEMORY;
  641. return NULL;
  642. }
  643. /* initialize result */
  644. result->pred = NULL;
  645. result->succ = NULL;
  646. result->nodes = NULL;
  647. return result;
  648. }
  649. /* free the memory associated with a given basic block */
  650. void finalizeBasicBlock(t_basic_block *block)
  651. {
  652. t_list *current_element;
  653. t_cflow_Node *current_node;
  654. if (block == NULL)
  655. return;
  656. if (block->pred != NULL)
  657. freeList(block->pred);
  658. if (block->succ != NULL)
  659. freeList(block->succ);
  660. /* initialize current_element */
  661. current_element = block->nodes;
  662. while (current_element != NULL)
  663. {
  664. /* retrieve the current node */
  665. current_node = (t_cflow_Node *) LDATA(current_element);
  666. /* free the memory associated with the current node */
  667. finalizeNode(current_node);
  668. /* retrieve the next node in the list */
  669. current_element = LNEXT(current_element);
  670. }
  671. freeList(block->nodes);
  672. /* free the memory associated with this basic block */
  673. _AXE_FREE_FUNCTION(block);
  674. }
  675. /* free the memory associated with a node of the graph */
  676. void finalizeNode(t_cflow_Node *node)
  677. {
  678. if (node == NULL)
  679. return;
  680. /* free the two lists `in' and `out' */
  681. if (node->in != NULL)
  682. freeList(node->in);
  683. if (node->out != NULL)
  684. freeList(node->out);
  685. /* free the current node */
  686. _AXE_FREE_FUNCTION(node);
  687. }
  688. t_cflow_Node * allocNode
  689. (t_cflow_Graph *graph, t_axe_instruction *instr)
  690. {
  691. t_cflow_Node *result;
  692. /* test the preconditions */
  693. if (graph == NULL) {
  694. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  695. return NULL;
  696. }
  697. if (instr == NULL)
  698. {
  699. cflow_errorcode = CFLOW_INVALID_INSTRUCTION;
  700. return NULL;
  701. }
  702. /* create a new instance of type `t_cflow_node' */
  703. result = _AXE_ALLOC_FUNCTION(sizeof(t_cflow_Node));
  704. /* test if an error occurred */
  705. if (result == NULL) {
  706. cflow_errorcode = CFLOW_OUT_OF_MEMORY;
  707. return NULL;
  708. }
  709. /* initialize result */
  710. result->def = NULL;
  711. result->uses[0] = NULL;
  712. result->uses[1] = NULL;
  713. result->uses[2] = NULL;
  714. result->instr = instr;
  715. /* set the def-uses for the current node */
  716. setDefUses(graph, result);
  717. /* test if an error occurred */
  718. if (cflow_errorcode != CFLOW_OK) {
  719. _AXE_FREE_FUNCTION(result);
  720. return NULL;
  721. }
  722. /* set the list of variables that are live in
  723. * and live out from the current node */
  724. result->in = NULL;
  725. result->out = NULL;
  726. /* return the node */
  727. return result;
  728. }
  729. void setPred(t_basic_block *block, t_basic_block *pred)
  730. {
  731. /* preconditions */
  732. if (block == NULL) {
  733. cflow_errorcode = CFLOW_BBLOCK_UNDEFINED;
  734. return;
  735. }
  736. if (pred == NULL) {
  737. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  738. return;
  739. }
  740. /* test if the block is already inserted in the list of predecessors */
  741. if (findElement(block->pred, pred) == NULL)
  742. {
  743. block->pred = addElement(block->pred, pred, -1);
  744. pred->succ = addElement(pred->succ, block, -1);
  745. }
  746. }
  747. void setSucc(t_basic_block *block, t_basic_block *succ)
  748. {
  749. t_list *element_found;
  750. /* preconditions */
  751. if (block == NULL) {
  752. cflow_errorcode = CFLOW_BBLOCK_UNDEFINED;
  753. return;
  754. }
  755. if (succ == NULL) {
  756. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  757. return;
  758. }
  759. element_found = findElement(block->succ, succ);
  760. /* test if the node is already inserted in the list of successors */
  761. if (element_found == NULL)
  762. {
  763. block->succ = addElement(block->succ, succ, -1);
  764. succ->pred = addElement(succ->pred, block, -1);
  765. }
  766. }
  767. void insertBlock(t_cflow_Graph *graph, t_basic_block *block)
  768. {
  769. /* preconditions */
  770. if (graph == NULL)
  771. {
  772. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  773. return;
  774. }
  775. if (block == NULL)
  776. {
  777. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  778. return;
  779. }
  780. if (findElement(graph->blocks, block) != NULL)
  781. {
  782. cflow_errorcode = CFLOW_BBLOCK_ALREADY_INSERTED;
  783. return;
  784. }
  785. /* add the current node to the basic block */
  786. graph->blocks = addElement(graph->blocks, block, -1);
  787. /* test if this is the first basic block for the program */
  788. if (graph->startingBlock == NULL)
  789. graph->startingBlock = block;
  790. }
  791. /* insert a new node without updating the dataflow informations */
  792. void insertNodeBefore(t_basic_block *block
  793. , t_cflow_Node *before_node, t_cflow_Node *new_node)
  794. {
  795. int before_node_posn;
  796. t_list *before_node_elem;
  797. /* preconditions */
  798. if (block == NULL)
  799. {
  800. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  801. return;
  802. }
  803. if ( (new_node == NULL)
  804. || (new_node->instr == NULL)
  805. || (before_node == NULL) )
  806. {
  807. cflow_errorcode = CFLOW_INVALID_NODE;
  808. return;
  809. }
  810. before_node_elem = findElement(block->nodes, before_node);
  811. if (before_node_elem == NULL)
  812. {
  813. cflow_errorcode = CFLOW_INVALID_NODE;
  814. return;
  815. }
  816. if (findElement(block->nodes, new_node) != NULL)
  817. {
  818. cflow_errorcode = CFLOW_NODE_ALREADY_INSERTED;
  819. return;
  820. }
  821. /* get the position of the before node */
  822. before_node_posn = getPosition(block->nodes, before_node_elem);
  823. assert(before_node_posn != -1);
  824. /* add the current node to the basic block */
  825. block->nodes = addElement(block->nodes, new_node, before_node_posn);
  826. }
  827. /* insert a new node without updating the dataflow informations */
  828. void insertNodeAfter(t_basic_block *block
  829. , t_cflow_Node *after_node, t_cflow_Node *new_node)
  830. {
  831. int after_node_posn;
  832. t_list *after_node_elem;
  833. /* preconditions */
  834. if (block == NULL)
  835. {
  836. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  837. return;
  838. }
  839. if ( (new_node == NULL)
  840. || (new_node->instr == NULL)
  841. || (after_node == NULL) )
  842. {
  843. cflow_errorcode = CFLOW_INVALID_NODE;
  844. return;
  845. }
  846. after_node_elem = findElement(block->nodes, after_node);
  847. if (after_node_elem == NULL)
  848. {
  849. cflow_errorcode = CFLOW_INVALID_NODE;
  850. return;
  851. }
  852. if (findElement(block->nodes, new_node) != NULL)
  853. {
  854. cflow_errorcode = CFLOW_NODE_ALREADY_INSERTED;
  855. return;
  856. }
  857. /* get the position of the after node */
  858. after_node_posn = getPosition(block->nodes, after_node_elem);
  859. assert(after_node_posn != -1);
  860. /* add the current node to the basic block */
  861. block->nodes = addElement(block->nodes, new_node, (after_node_posn + 1));
  862. }
  863. void insertNode(t_basic_block *block, t_cflow_Node *node)
  864. {
  865. /* preconditions */
  866. if (block == NULL)
  867. {
  868. cflow_errorcode = CFLOW_INVALID_BBLOCK;
  869. return;
  870. }
  871. if (node == NULL || node->instr == NULL)
  872. {
  873. cflow_errorcode = CFLOW_INVALID_NODE;
  874. return;
  875. }
  876. if (findElement(block->nodes, node) != NULL)
  877. {
  878. cflow_errorcode = CFLOW_NODE_ALREADY_INSERTED;
  879. return;
  880. }
  881. /* add the current node to the basic block */
  882. block->nodes = addElement(block->nodes, node, -1);
  883. }
  884. t_cflow_Graph * createFlowGraph(t_list *instructions)
  885. {
  886. t_cflow_Graph *result;
  887. t_basic_block *bblock;
  888. t_list *current_element;
  889. t_cflow_Node *current_node;
  890. t_axe_instruction *current_instr;
  891. int startingNode;
  892. int endingNode;
  893. /* initialize the global variable `cflow_errorcode' */
  894. cflow_errorcode = CFLOW_OK;
  895. /* preconditions */
  896. if (instructions == NULL){
  897. cflow_errorcode = CFLOW_INVALID_PROGRAM_INFO;
  898. return NULL;
  899. }
  900. /* alloc memory for a new control flow graph */
  901. result = allocGraph();
  902. if (result == NULL)
  903. return NULL;
  904. /* set the starting basic block */
  905. bblock = NULL;
  906. /* initialize the current element */
  907. current_element = instructions;
  908. while(current_element != NULL)
  909. {
  910. /* retrieve the current instruction */
  911. current_instr = (t_axe_instruction *) LDATA(current_element);
  912. assert(current_instr != NULL);
  913. if (isLoadInstruction(current_instr))
  914. {
  915. current_element = LNEXT(current_element);
  916. continue;
  917. }
  918. /* create a new node for the current basic block */
  919. current_node = allocNode(result, current_instr);
  920. if (current_node == NULL){
  921. finalizeGraph(result);
  922. return NULL;
  923. }
  924. /* test if the current instruction will start or end a block */
  925. startingNode = isStartingNode(current_instr);
  926. endingNode = isEndingNode(current_instr);
  927. if (startingNode || bblock == NULL)
  928. {
  929. /* alloc a new basic block */
  930. bblock = allocBasicBlock();
  931. if (bblock == NULL) {
  932. finalizeGraph(result);
  933. finalizeNode(current_node);
  934. return NULL;
  935. }
  936. /* add the current instruction to the newly created
  937. * basic block */
  938. insertNode(bblock, current_node);
  939. if (cflow_errorcode != CFLOW_OK) {
  940. finalizeGraph(result);
  941. finalizeNode(current_node);
  942. finalizeBasicBlock(bblock);
  943. return NULL;
  944. }
  945. /* add the new basic block to the control flow graph */
  946. insertBlock(result, bblock);
  947. if (cflow_errorcode != CFLOW_OK) {
  948. finalizeGraph(result);
  949. finalizeNode(current_node);
  950. finalizeBasicBlock(bblock);
  951. return NULL;
  952. }
  953. }
  954. else
  955. {
  956. /* add the current instruction to the current
  957. * basic block */
  958. insertNode(bblock, current_node);
  959. if (cflow_errorcode != CFLOW_OK) {
  960. finalizeGraph(result);
  961. finalizeNode(current_node);
  962. return NULL;
  963. }
  964. }
  965. if (endingNode)
  966. bblock = NULL;
  967. /* retrieve the next element */
  968. current_element = LNEXT(current_element);
  969. }
  970. /* update the basic blocks chain */
  971. updateFlowGraph(result);
  972. if (cflow_errorcode != CFLOW_OK) {
  973. finalizeGraph(result);
  974. return NULL;
  975. }
  976. /*return the graph */
  977. return result;
  978. }
  979. void updateFlowGraph(t_cflow_Graph *graph)
  980. {
  981. t_list *current_element;
  982. t_basic_block *current_block;
  983. t_basic_block *successor;
  984. /* preconditions: graph should not be a NULL pointer */
  985. if (graph == NULL){
  986. cflow_errorcode = CFLOW_GRAPH_UNDEFINED;
  987. return;
  988. }
  989. successor = NULL;
  990. current_element = graph->blocks;
  991. while(current_element != NULL)
  992. {
  993. t_list *last_element;
  994. t_cflow_Node *last_node;
  995. t_axe_instruction *last_instruction;
  996. t_basic_block *jumpBlock;
  997. /* retrieve the current block */
  998. current_block = (t_basic_block *) LDATA(current_element);
  999. assert(current_block != NULL);
  1000. assert(current_block->nodes != NULL);
  1001. /* get the last node of the basic block */
  1002. last_element = getLastElement(current_block->nodes);
  1003. assert(last_element != NULL);
  1004. last_node = (t_cflow_Node *) LDATA(last_element);
  1005. assert(last_node != NULL);
  1006. last_instruction = last_node->instr;
  1007. assert(last_instruction != NULL);
  1008. if (isHaltInstruction(last_instruction))
  1009. {
  1010. setSucc(current_block, graph->endingBlock);
  1011. setPred(graph->endingBlock, current_block);
  1012. }
  1013. else
  1014. {
  1015. if (isJumpInstruction(last_instruction))
  1016. {
  1017. if ( (last_instruction->address == NULL)
  1018. || ((last_instruction->address)->labelID == NULL) )
  1019. {
  1020. cflow_errorcode = CFLOW_INVALID_LABEL_FOUND;
  1021. return;
  1022. }
  1023. jumpBlock = searchLabel(graph
  1024. , (last_instruction->address)->labelID);
  1025. if (jumpBlock == NULL) {
  1026. cflow_errorcode = CFLOW_INVALID_LABEL_FOUND;
  1027. return;
  1028. }
  1029. /* add the jumpBlock to the list of successors of current_block */
  1030. /* add also current_block to the list of predecessors of jumpBlock */
  1031. setPred(jumpBlock, current_block);
  1032. if (cflow_errorcode != CFLOW_OK)
  1033. return;
  1034. setSucc(current_block, jumpBlock);
  1035. if (cflow_errorcode != CFLOW_OK)
  1036. return;
  1037. }
  1038. if (!isUnconditionalJump(last_instruction))
  1039. {
  1040. t_basic_block *nextBlock;
  1041. t_list *next_element;
  1042. next_element = LNEXT(current_element);
  1043. if (next_element != NULL)
  1044. {
  1045. nextBlock = LDATA(next_element);
  1046. assert(nextBlock != NULL);
  1047. setSucc(current_block, nextBlock);
  1048. setPred(nextBlock, current_block);
  1049. }
  1050. else
  1051. {
  1052. setSucc(current_block, graph->endingBlock);
  1053. setPred(graph->endingBlock, current_block);
  1054. }
  1055. if (cflow_errorcode != CFLOW_OK)
  1056. return;
  1057. }
  1058. }
  1059. /* update the value of `current_element' */
  1060. current_element = LNEXT(current_element);
  1061. }
  1062. }