axe_utils.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Andrea Di Biagio
  3. * Politecnico di Milano, 2007
  4. *
  5. * axe_utils.c
  6. * Formal Languages & Compilers Machine, 2007/2008
  7. *
  8. */
  9. #include <stdio.h>
  10. #include "axe_utils.h"
  11. #include "axe_gencode.h"
  12. #include "symbol_table.h"
  13. #include "axe_labels.h"
  14. #include "axe_cflow_graph.h"
  15. #include "axe_reg_alloc.h"
  16. #include "axe_io_manager.h"
  17. #include "axe_errors.h"
  18. extern int errorcode;
  19. extern int line_num;
  20. extern int num_error;
  21. extern int num_warning;
  22. extern t_program_infos *program;
  23. extern t_cflow_Graph *graph;
  24. extern t_reg_allocator *RA;
  25. extern t_io_infos *file_infos;
  26. static void free_new_variables(t_list *variables)
  27. {
  28. t_list *current_element;
  29. t_axe_declaration *current_decl;
  30. /* preconditions */
  31. assert(variables != NULL);
  32. /* initialize the value of `current_element' */
  33. current_element = variables;
  34. while(current_element != NULL)
  35. {
  36. current_decl = (t_axe_declaration *) LDATA(current_element);
  37. if (current_decl != NULL)
  38. _AXE_FREE_FUNCTION(current_decl);
  39. current_element = LNEXT(current_element);
  40. }
  41. /* free the memory associated with the list `variables' */
  42. freeList(variables);
  43. }
  44. void set_new_variables(t_program_infos *program
  45. , int varType, t_list *variables)
  46. {
  47. t_list *current_element;
  48. t_axe_declaration *current_decl;
  49. int counter;
  50. /* preconditions */
  51. if (program == NULL){
  52. free_new_variables(variables);
  53. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  54. }
  55. /* initialize `current_element' */
  56. current_element = variables;
  57. counter = 1;
  58. while (current_element != NULL)
  59. {
  60. /* retrieve the current declaration infos */
  61. current_decl = (t_axe_declaration *) LDATA(current_element);
  62. if (current_decl == NULL) {
  63. free_new_variables(variables);
  64. notifyError(AXE_NULL_DECLARATION);
  65. }
  66. /* create and assign a new variable to program */
  67. createVariable(program, current_decl->ID, varType, current_decl->isArray
  68. , current_decl->arraySize, current_decl->init_val);
  69. /* update the value of `current_element' */
  70. current_element = LNEXT(current_element);
  71. }
  72. /* free the linked list */
  73. /* initialize `current_element' */
  74. current_element = variables;
  75. while (current_element != NULL)
  76. {
  77. /* retrieve the current declaration infos */
  78. current_decl = (t_axe_declaration *) LDATA(current_element);
  79. /* assertion -- must always be verified */
  80. assert(current_decl != NULL);
  81. /* add a load instruction for each declared variable
  82. * that is not an array type */
  83. if (!(current_decl->isArray))
  84. get_symbol_location(program, current_decl->ID, 0);
  85. /* free the memory associated with the current declaration */
  86. _AXE_FREE_FUNCTION(current_decl);
  87. /* update the value of `current_element' */
  88. current_element = LNEXT(current_element);
  89. }
  90. freeList(variables);
  91. }
  92. int get_symbol_location(t_program_infos *program, char *ID, int genLoad)
  93. {
  94. int sy_error;
  95. int location;
  96. /* preconditions: ID and program shouldn't be NULL pointer */
  97. if (ID == NULL)
  98. notifyError(AXE_VARIABLE_ID_UNSPECIFIED);
  99. if (program == NULL)
  100. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  101. /* get the location of the symbol with the given ID */
  102. location = getLocation(program->sy_table, ID, &sy_error);
  103. if (sy_error != SY_TABLE_OK)
  104. notifyError(AXE_INVALID_VARIABLE);
  105. /* verify if the variable was previously loaded into
  106. * a register. This check is made by looking to the
  107. * value of `location'.*/
  108. if (location == REG_INVALID)
  109. {
  110. /* we have to load the variable with the given
  111. * identifier (ID) */
  112. t_axe_label *label;
  113. int sy_errorcode;
  114. /* retrieve the label associated with ID */
  115. label = getLabelFromVariableID(program, ID);
  116. /* fetch an unused register where to store the
  117. * result of the load instruction */
  118. location = getNewRegister(program);
  119. /* assertions */
  120. assert(location != REG_INVALID);
  121. assert( (label != NULL)
  122. && (label->labelID != LABEL_UNSPECIFIED) );
  123. /* load the value of IDENTIFIER from the
  124. * given label to a register */
  125. if (genLoad)
  126. gen_load_instruction(program, location, label, 0);
  127. /* update the symbol table */
  128. sy_errorcode = setLocation(program->sy_table, ID, location);
  129. if (sy_errorcode != SY_TABLE_OK)
  130. notifyError(AXE_SY_TABLE_ERROR);
  131. #ifndef NDEBUG
  132. /* get the location of the symbol with the given ID */
  133. location = getLocation(program->sy_table, ID, &sy_error);
  134. #endif
  135. }
  136. /* test the postconditions */
  137. assert(location != REG_INVALID);
  138. return location;
  139. }
  140. int is_int16(int immediate) {
  141. return immediate < (1 << 15) && immediate >= -(1 << 15);
  142. }
  143. int is_int20(int immediate) {
  144. return immediate < (1 << 19) && immediate >= -(1 << 19);
  145. }
  146. void gen_move_immediate(t_program_infos *program, int dest, int immediate)
  147. {
  148. if (is_int20(immediate)) {
  149. /* immediate fits in a a 20-bit signed integer */
  150. gen_mova_instruction(program, dest, NULL, immediate);
  151. } else {
  152. /* immediate does not fit in a 20-bit signed integer */
  153. int lo = (immediate << 16) >> 16;
  154. int hi = (immediate - lo) >> 16;
  155. gen_addi_instruction(program, dest, REG_0, hi);
  156. gen_shli_instruction(program, dest, dest, 16);
  157. gen_addi_instruction(program, dest, dest, lo);
  158. }
  159. }
  160. int gen_load_immediate(t_program_infos *program, int immediate)
  161. {
  162. int imm_register;
  163. imm_register = getNewRegister(program);
  164. gen_move_immediate(program, imm_register, immediate);
  165. return imm_register;
  166. }
  167. void set_end_Program(t_program_infos *program)
  168. {
  169. if (program == NULL)
  170. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  171. if (isAssignedLabel(program->lmanager))
  172. {
  173. gen_halt_instruction(program);
  174. return;
  175. }
  176. if (program->instructions != NULL)
  177. {
  178. t_axe_instruction *last_instr;
  179. t_list *last_element;
  180. /* get the last element of the list */
  181. last_element = getLastElement(program->instructions);
  182. assert(last_element != NULL);
  183. /* retrieve the last instruction */
  184. last_instr = (t_axe_instruction *) LDATA(last_element);
  185. assert(last_instr != NULL);
  186. if (last_instr->opcode == HALT)
  187. return;
  188. }
  189. gen_halt_instruction(program);
  190. return;
  191. }
  192. void shutdownCompiler(int exitStatus)
  193. {
  194. #ifndef NDEBUG
  195. fprintf(stdout, "Finalizing the compiler data structures.. \n");
  196. #endif
  197. /* shutdown the asm engine */
  198. finalizeProgramInfos(program);
  199. /* finalize the control flow graph informations */
  200. finalizeGraph(graph);
  201. /* finalize the register allocator */
  202. finalizeRegAlloc(RA);
  203. /* close all the files used by the compiler */
  204. finalizeOutputInfos(file_infos);
  205. #ifndef NDEBUG
  206. fprintf(stdout, "Done. \n");
  207. #endif
  208. exit(exitStatus);
  209. }
  210. void init_compiler(int argc, char **argv)
  211. {
  212. #ifndef NDEBUG
  213. fprintf(stdout, "Starting the compilation process. \n\n");
  214. #endif
  215. /* initialize all the global variables */
  216. errorcode = AXE_OK;
  217. line_num = -1;
  218. num_error = 0;
  219. num_warning = 0;
  220. program = NULL;
  221. graph = NULL;
  222. RA = NULL;
  223. file_infos = NULL;
  224. #ifndef NDEBUG
  225. fprintf(stdout, "Initialize the compiler internal data structures. \n");
  226. #endif
  227. /* initialize all the files used by the compiler */
  228. file_infos = initializeOutputInfos(argc, argv);
  229. if (file_infos == NULL)
  230. errorcode = AXE_OUT_OF_MEMORY;
  231. /* initialize the translation infos */
  232. program = allocProgramInfos(&errorcode);
  233. /* initialize the line number */
  234. line_num = 1;
  235. checkConsistency();
  236. }