123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /*
- * Andrea Di Biagio
- * Politecnico di Milano, 2007
- *
- * axe_utils.c
- * Formal Languages & Compilers Machine, 2007/2008
- *
- */
- #include <stdio.h>
- #include "axe_utils.h"
- #include "axe_gencode.h"
- #include "symbol_table.h"
- #include "axe_labels.h"
- #include "axe_cflow_graph.h"
- #include "axe_reg_alloc.h"
- #include "axe_io_manager.h"
- #include "axe_errors.h"
- extern int errorcode;
- extern int line_num;
- extern int num_error;
- extern int num_warning;
- extern t_program_infos *program;
- extern t_cflow_Graph *graph;
- extern t_reg_allocator *RA;
- extern t_io_infos *file_infos;
- static void free_new_variables(t_list *variables)
- {
- t_list *current_element;
- t_axe_declaration *current_decl;
- /* preconditions */
- assert(variables != NULL);
- /* initialize the value of `current_element' */
- current_element = variables;
- while(current_element != NULL)
- {
- current_decl = (t_axe_declaration *) LDATA(current_element);
- if (current_decl != NULL)
- _AXE_FREE_FUNCTION(current_decl);
- current_element = LNEXT(current_element);
- }
- /* free the memory associated with the list `variables' */
- freeList(variables);
- }
- void set_new_variables(t_program_infos *program
- , int varType, t_list *variables)
- {
- t_list *current_element;
- t_axe_declaration *current_decl;
- int counter;
- /* preconditions */
- if (program == NULL){
- free_new_variables(variables);
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
- }
-
- /* initialize `current_element' */
- current_element = variables;
- counter = 1;
- while (current_element != NULL)
- {
- /* retrieve the current declaration infos */
- current_decl = (t_axe_declaration *) LDATA(current_element);
- if (current_decl == NULL) {
- free_new_variables(variables);
- notifyError(AXE_NULL_DECLARATION);
- }
- /* create and assign a new variable to program */
- createVariable(program, current_decl->ID, varType, current_decl->isArray
- , current_decl->arraySize, current_decl->init_val);
- /* update the value of `current_element' */
- current_element = LNEXT(current_element);
- }
- /* free the linked list */
- /* initialize `current_element' */
- current_element = variables;
- while (current_element != NULL)
- {
- /* retrieve the current declaration infos */
- current_decl = (t_axe_declaration *) LDATA(current_element);
- /* assertion -- must always be verified */
- assert(current_decl != NULL);
- /* add a load instruction for each declared variable
- * that is not an array type */
- if (!(current_decl->isArray))
- get_symbol_location(program, current_decl->ID, 0);
- /* free the memory associated with the current declaration */
- _AXE_FREE_FUNCTION(current_decl);
- /* update the value of `current_element' */
- current_element = LNEXT(current_element);
- }
- freeList(variables);
- }
- int get_symbol_location(t_program_infos *program, char *ID, int genLoad)
- {
- int sy_error;
- int location;
- /* preconditions: ID and program shouldn't be NULL pointer */
- if (ID == NULL)
- notifyError(AXE_VARIABLE_ID_UNSPECIFIED);
- if (program == NULL)
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
-
- /* get the location of the symbol with the given ID */
- location = getLocation(program->sy_table, ID, &sy_error);
- if (sy_error != SY_TABLE_OK)
- notifyError(AXE_INVALID_VARIABLE);
- /* verify if the variable was previously loaded into
- * a register. This check is made by looking to the
- * value of `location'.*/
- if (location == REG_INVALID)
- {
- /* we have to load the variable with the given
- * identifier (ID) */
- t_axe_label *label;
- int sy_errorcode;
- /* retrieve the label associated with ID */
- label = getLabelFromVariableID(program, ID);
- /* fetch an unused register where to store the
- * result of the load instruction */
- location = getNewRegister(program);
- /* assertions */
- assert(location != REG_INVALID);
- assert( (label != NULL)
- && (label->labelID != LABEL_UNSPECIFIED) );
-
- /* load the value of IDENTIFIER from the
- * given label to a register */
- if (genLoad)
- gen_load_instruction(program, location, label, 0);
- /* update the symbol table */
- sy_errorcode = setLocation(program->sy_table, ID, location);
- if (sy_errorcode != SY_TABLE_OK)
- notifyError(AXE_SY_TABLE_ERROR);
- #ifndef NDEBUG
- /* get the location of the symbol with the given ID */
- location = getLocation(program->sy_table, ID, &sy_error);
- #endif
- }
- /* test the postconditions */
- assert(location != REG_INVALID);
- return location;
- }
- int is_int16(int immediate) {
- return immediate < (1 << 15) && immediate >= -(1 << 15);
- }
- int is_int20(int immediate) {
- return immediate < (1 << 19) && immediate >= -(1 << 19);
- }
- void gen_move_immediate(t_program_infos *program, int dest, int immediate)
- {
- if (is_int20(immediate)) {
- /* immediate fits in a a 20-bit signed integer */
- gen_mova_instruction(program, dest, NULL, immediate);
- } else {
- /* immediate does not fit in a 20-bit signed integer */
- int lo = (immediate << 16) >> 16;
- int hi = (immediate - lo) >> 16;
- gen_addi_instruction(program, dest, REG_0, hi);
- gen_shli_instruction(program, dest, dest, 16);
- gen_addi_instruction(program, dest, dest, lo);
- }
- }
- int gen_load_immediate(t_program_infos *program, int immediate)
- {
- int imm_register;
- imm_register = getNewRegister(program);
- gen_move_immediate(program, imm_register, immediate);
- return imm_register;
- }
- void set_end_Program(t_program_infos *program)
- {
- if (program == NULL)
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
-
- if (isAssignedLabel(program->lmanager))
- {
- gen_halt_instruction(program);
- return;
- }
- if (program->instructions != NULL)
- {
- t_axe_instruction *last_instr;
- t_list *last_element;
- /* get the last element of the list */
- last_element = getLastElement(program->instructions);
- assert(last_element != NULL);
- /* retrieve the last instruction */
- last_instr = (t_axe_instruction *) LDATA(last_element);
- assert(last_instr != NULL);
- if (last_instr->opcode == HALT)
- return;
- }
- gen_halt_instruction(program);
- return;
- }
- void shutdownCompiler(int exitStatus)
- {
- #ifndef NDEBUG
- fprintf(stdout, "Finalizing the compiler data structures.. \n");
- #endif
-
- /* shutdown the asm engine */
- finalizeProgramInfos(program);
- /* finalize the control flow graph informations */
- finalizeGraph(graph);
- /* finalize the register allocator */
- finalizeRegAlloc(RA);
- /* close all the files used by the compiler */
- finalizeOutputInfos(file_infos);
-
- #ifndef NDEBUG
- fprintf(stdout, "Done. \n");
- #endif
-
- exit(exitStatus);
- }
- void init_compiler(int argc, char **argv)
- {
- #ifndef NDEBUG
- fprintf(stdout, "Starting the compilation process. \n\n");
- #endif
- /* initialize all the global variables */
- errorcode = AXE_OK;
- line_num = -1;
- num_error = 0;
- num_warning = 0;
- program = NULL;
- graph = NULL;
- RA = NULL;
- file_infos = NULL;
- #ifndef NDEBUG
- fprintf(stdout, "Initialize the compiler internal data structures. \n");
- #endif
-
- /* initialize all the files used by the compiler */
- file_infos = initializeOutputInfos(argc, argv);
- if (file_infos == NULL)
- errorcode = AXE_OUT_OF_MEMORY;
- /* initialize the translation infos */
- program = allocProgramInfos(&errorcode);
-
- /* initialize the line number */
- line_num = 1;
- checkConsistency();
- }
|