12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061 |
- /*
- * Andrea Di Biagio
- * Politecnico di Milano, 2007
- *
- * axe_transform.c
- * Formal Languages & Compilers Machine, 2007/2008
- *
- */
- #include "axe_transform.h"
- #include "symbol_table.h"
- #include "cflow_constants.h"
- #include "reg_alloc_constants.h"
- #include "axe_errors.h"
- #include "axe_debug.h"
- extern int errorcode;
- extern int cflow_errorcode;
- typedef struct t_tempLabel
- {
- t_axe_label *labelID;
- int regID;
- } t_tempLabel;
- static t_axe_instruction * _createUnary (t_program_infos *program
- , int reg, t_axe_label *label, int opcode);
- static t_axe_instruction * createUnaryInstruction
- (t_program_infos *program, int reg, int opcode);
- static t_tempLabel * allocTempLabel(t_axe_label *labelID, int regID);
- static void freeTempLabel(t_tempLabel *tempLabel);
- static void finalizeListOfTempLabels(t_list *tempLabels);
- static int compareTempLabels(void *valA, void *valB);
- /* create new locations into the data segment in order to manage correctly
- * spilled variables */
- static void updateTheDataSegment
- (t_program_infos *program, t_list *tempLabels);
- static void updateTheCodeSegment
- (t_program_infos *program, t_cflow_Graph *graph);
- static t_list * _insertLoad(t_program_infos *program, t_cflow_Graph *graph
- , t_basic_block *block, t_cflow_Node *current_node
- , t_cflow_var *var, t_list *usedVars);
- static t_list * _insertStore(t_program_infos *program, t_cflow_Graph *graph
- , t_basic_block *block, t_cflow_Node *current_node
- , t_cflow_var *var, t_list *usedVars);
-
- /* create a load instruction without assigning it to program */
- static t_axe_instruction * createLoadInstruction
- (t_program_infos *program, int reg);
- /* create a store instruction without assigning it to program */
- static t_axe_instruction * createStoreInstruction
- (t_program_infos *program, int reg);
- /* update the control flow informations by unsing the result
- * of the register allocation process and a list of bindings
- * between new assembly labels and spilled variables */
- static void updatCflowInfos(t_program_infos *program, t_cflow_Graph *graph
- , t_reg_allocator *RA, t_list *label_bindings);
- /* this function returns a list of t_templabel containing binding
- * informations between spilled variables and labels that will point
- * to a memory block in the data segment */
- static t_list * retrieveLabelBindings(t_program_infos *program, t_reg_allocator *RA);
-
- int _insertLoadSpill(t_program_infos *program, int temp_register, int selected_register
- , t_cflow_Graph *graph, t_basic_block *current_block
- , t_cflow_Node *current_node, t_list *labelBindings, int before);
-
- int _insertStoreSpill(t_program_infos *program, int temp_register, int selected_register
- , t_cflow_Graph *graph, t_basic_block *current_block
- , t_cflow_Node *current_node, t_list *labelBindings, int before);
-
- static t_list * _insertStore(t_program_infos *program, t_cflow_Graph *graph
- , t_basic_block *current_block, t_cflow_Node *current_node
- , t_cflow_var *var, t_list *usedVars)
- {
- /* we have to insert a store instruction into the code */
- t_axe_instruction *storeInstr;
- t_cflow_Node *storeNode;
- /* create a load instruction */
- storeInstr = createStoreInstruction
- (program, var->ID);
- /* test if an error occurred */
- if (errorcode != AXE_OK) {
- free_Instruction(storeInstr);
- notifyError(errorcode);
- }
-
- if (storeInstr != NULL)
- {
- /* create a node for the store instruction */
- storeNode = allocNode (graph, storeInstr);
- if (cflow_errorcode != CFLOW_OK) {
- finalizeNode(storeNode);
- free_Instruction(storeInstr);
- return usedVars;
- }
- /* insert the node `loadNode' before `current_node' */
- insertNodeAfter(current_block, current_node, storeNode);
-
- /* update the list of usedVars */
- usedVars = removeElement(usedVars, storeNode->uses[0]);
- }
- return usedVars;
- }
- t_list * _insertLoad(t_program_infos *program, t_cflow_Graph *graph
- , t_basic_block *current_block, t_cflow_Node *current_node
- , t_cflow_var *var, t_list *usedVars)
- {
- /* we have to insert a load instruction into the code */
- t_axe_instruction *current_instr;
- t_axe_instruction *loadInstr;
- t_cflow_Node *loadNode;
- /* retrieve the current instruction from the current node */
- current_instr = current_node->instr;
- /* create a load instruction */
- loadInstr = createLoadInstruction
- (program, var->ID);
- /* test if an error occurred */
- if (errorcode != AXE_OK) {
- free_Instruction(loadInstr);
- notifyError(errorcode);
- }
- if (loadInstr != NULL)
- {
- /* create a node for the load instruction */
- loadNode = allocNode (graph, loadInstr);
- /* test if an error occurred */
- if (cflow_errorcode != CFLOW_OK) {
- finalizeNode(loadNode);
- free_Instruction(loadInstr);
- return usedVars;
- }
- /* update the label informations */
- if (current_instr->labelID != NULL) {
- loadInstr->labelID = current_instr->labelID;
- current_instr->labelID = NULL;
- }
-
- /* insert the node `loadNode' before `current_node' */
- insertNodeBefore(current_block, current_node, loadNode);
- /* update the list of usedVars */
- usedVars = addElement(usedVars, loadNode->def, -1);
- }
- return usedVars;
- }
- void updateTheCodeSegment(t_program_infos *program, t_cflow_Graph *graph)
- {
- t_list *current_bb_element;
- t_list *current_nd_element;
- t_basic_block *bblock;
- t_cflow_Node *node;
-
- /* preconditions */
- if (program == NULL)
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
- if (graph == NULL)
- notifyError(AXE_INVALID_CFLOW_GRAPH);
- current_bb_element = graph->blocks;
- while(current_bb_element != NULL)
- {
- bblock = (t_basic_block *) LDATA(current_bb_element);
- current_nd_element = bblock->nodes;
- while(current_nd_element != NULL)
- {
- node = (t_cflow_Node *) LDATA(current_nd_element);
- program->instructions =
- addElement(program->instructions, node->instr, -1);
-
- current_nd_element = LNEXT(current_nd_element);
- }
- current_bb_element = LNEXT(current_bb_element);
- }
- }
- void updateTheDataSegment(t_program_infos *program, t_list *labelBindings)
- {
- t_list *current_element;
- t_tempLabel *current_TL;
- t_axe_data *new_data_info;
- /* preconditions */
- if (program == NULL) {
- finalizeListOfTempLabels(labelBindings);
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
- }
- /* initialize the value of `current_element' */
- current_element = labelBindings;
- while(current_element != NULL)
- {
- current_TL = (t_tempLabel *) LDATA(current_element);
- new_data_info = alloc_data (DIR_WORD, 0, current_TL->labelID);
-
- if (new_data_info == NULL){
- finalizeListOfTempLabels(labelBindings);
- notifyError(AXE_OUT_OF_MEMORY);
- }
- /* update the list of directives */
- program->data = addElement(program->data, new_data_info, -1);
-
- current_element = LNEXT(current_element);
- }
- }
- t_axe_instruction * _createUnary (t_program_infos *program
- , int reg, t_axe_label *label, int opcode)
- {
- t_axe_instruction *result;
-
- /* preconditions */
- if (program == NULL) {
- errorcode = AXE_PROGRAM_NOT_INITIALIZED;
- return NULL;
- }
-
- if (label == NULL) {
- errorcode = AXE_INVALID_LABEL;
- return NULL;
- }
- /* create an instance of `t_axe_instruction' */
- result = alloc_instruction(opcode);
- if (result == NULL) {
- errorcode = AXE_OUT_OF_MEMORY;
- return NULL;
- }
- result->reg_1 = alloc_register(reg, 0);
- if (result->reg_1 == NULL) {
- errorcode = AXE_OUT_OF_MEMORY;
- free_Instruction(result);
- return NULL;
- }
- /* initialize an address info */
- result->address = alloc_address(LABEL_TYPE, 0, label);
- if (result->address == NULL) {
- errorcode = AXE_OUT_OF_MEMORY;
- free_Instruction(result);
- return NULL;
- }
- return result;
- }
- int compareTempLabels(void *valA, void *valB)
- {
- t_tempLabel *tlA;
- t_tempLabel *tlB;
-
- if (valA == NULL)
- return 0;
- if (valB == NULL)
- return 0;
- tlA = (t_tempLabel *) valA;
- tlB = (t_tempLabel *) valB;
- return (tlA->regID == tlB->regID);
- }
- t_tempLabel * allocTempLabel(t_axe_label *labelID, int regID)
- {
- t_tempLabel *result;
- /* preconditions */
- if (labelID == NULL) {
- errorcode = AXE_INVALID_LABEL;
- return NULL;
- }
- /* create a new temp-label */
- result = _AXE_ALLOC_FUNCTION(sizeof(t_tempLabel));
- if (result == NULL) {
- errorcode = AXE_OUT_OF_MEMORY;
- return NULL;
- }
-
- /* initialize the temp label */
- result->labelID = labelID;
- result->regID = regID;
- return result;
- }
- void freeTempLabel(t_tempLabel *tempLabel)
- {
- if (tempLabel != NULL)
- _AXE_FREE_FUNCTION(tempLabel);
- }
- void finalizeListOfTempLabels(t_list *tempLabels)
- {
- t_list *current_element;
- t_tempLabel *tempLabel;
- /* test the preconditions */
- if (tempLabels == NULL)
- return;
- /* assign to current_element the address of the first
- * element of the list `tempLabels' */
- current_element = tempLabels;
-
- while(current_element != NULL)
- {
- tempLabel = (t_tempLabel *) LDATA(current_element);
- if (tempLabel != NULL)
- freeTempLabel(tempLabel);
-
- current_element = LNEXT(current_element);
- }
- /* finalize the list of elements of type `t_tempLabel' */
- freeList(tempLabels);
- }
- void updateProgramInfos(t_program_infos *program
- , t_cflow_Graph *graph, t_reg_allocator *RA)
- {
- t_list *label_bindings;
- /* retrieve a list of t_templabels for the given RA infos.*/
- label_bindings = retrieveLabelBindings(program, RA);
- /* update the content of the data segment */
- updateTheDataSegment(program, label_bindings);
-
- /* update the control flow graph with the reg-alloc infos. */
- updatCflowInfos(program, graph, RA, label_bindings);
- /* erase the old code segment */
- freeList(program->instructions);
- program->instructions = NULL;
- /* update the code segment informations */
- updateTheCodeSegment(program, graph);
- /* finalize the list of tempLabels */
- finalizeListOfTempLabels(label_bindings);
- }
- t_list * retrieveLabelBindings(t_program_infos *program, t_reg_allocator *RA)
- {
- int counter;
- t_list *result;
- t_tempLabel *tlabel;
- t_axe_label *axe_label;
-
- /* preconditions */
- if (program == NULL)
- notifyError(AXE_PROGRAM_NOT_INITIALIZED);
- if (RA == NULL)
- notifyError(AXE_INVALID_REG_ALLOC);
- /* initialize the local variable `result' */
- result = NULL;
- tlabel = NULL;
- for (counter = 0; counter <= RA->varNum; counter++)
- {
- if (RA->bindings[counter] == RA_SPILL_REQUIRED)
- {
- /* retrieve a new label */
- axe_label = newLabel(program);
- if (axe_label == NULL)
- notifyError(AXE_INVALID_LABEL);
- /* create a new tempLabel */
- tlabel = allocTempLabel(axe_label, counter);
- /* add the current tlabel to the list of labelbindings */
- result = addElement(result, tlabel, -1);
- }
- }
-
- /* postcondition: return the list of bindings */
- return result;
- }
- t_axe_instruction * createUnaryInstruction
- (t_program_infos *program, int reg, int opcode)
- {
- char *varID;
- int sy_errorcode;
- t_axe_variable *axe_var;
- /* test the preconditions */
- if ((reg == REG_INVALID) || (reg == REG_0)) {
- errorcode = AXE_INVALID_REGISTER_INFO;
- return NULL;
- }
- if (program == NULL || program->sy_table == NULL) {
- errorcode = AXE_PROGRAM_NOT_INITIALIZED;
- return NULL;
- }
- /* initialize the value of errorcode */
- sy_errorcode = SY_TABLE_OK;
- varID = getIDfromLocation(program->sy_table, reg, &sy_errorcode);
- if (varID == NULL)
- return NULL;
- /* retrieve the variable associated with `varID' */
- axe_var = getVariable (program, varID);
- return _createUnary (program, reg, axe_var->labelID, opcode);
- }
- t_axe_instruction * createStoreInstruction
- (t_program_infos *program, int reg)
- {
- return createUnaryInstruction(program, reg, STORE);
- }
- t_axe_instruction * createLoadInstruction
- (t_program_infos *program, int reg)
- {
- return createUnaryInstruction(program, reg, LOAD);
- }
- t_cflow_Graph * insertLoadAndStoreInstr
- (t_program_infos *program, t_cflow_Graph *graph)
- {
- t_list *current_bb_element;
- t_basic_block *current_block;
- t_list *current_nd_element;
- t_cflow_Node *current_node;
- t_list *usedVars;
- /* assertions */
- assert(program != NULL);
- assert(graph != NULL);
-
- /* initialize the list of variables used by this basic block */
- usedVars = NULL;
- current_bb_element = graph->blocks;
- while (current_bb_element != NULL)
- {
- current_block = (t_basic_block *) LDATA(current_bb_element);
- /* retrieve the list of nodes for the current basic block */
- current_nd_element = current_block->nodes;
- while(current_nd_element != NULL)
- {
- current_node = (t_cflow_Node *) LDATA(current_nd_element);
- /* test if we have to insert a store */
- if ( (current_node->def != NULL)
- && ((current_node->def)->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->def) == NULL)
- {
- usedVars = addElement(usedVars, current_node->def, -1);
- }
- }
- /* test if we have to insert a load */
- if ( (current_node->uses[0] != NULL)
- && ((current_node->uses[0])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[0]) == NULL)
- {
- usedVars = _insertLoad(program, graph, current_block
- , current_node, current_node->uses[0], usedVars);
- }
- }
- if ( (current_node->uses[1] != NULL)
- && ((current_node->uses[1])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[1]) == NULL)
- {
- usedVars = _insertLoad(program, graph, current_block
- , current_node, current_node->uses[1], usedVars);
- }
- }
- if ( (current_node->uses[2] != NULL)
- && ((current_node->uses[2])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[2]) == NULL)
- {
- usedVars = _insertLoad(program, graph, current_block
- , current_node, current_node->uses[2], usedVars);
- }
- }
- /* retrieve the next element */
- current_nd_element = LNEXT(current_nd_element);
- }
- current_nd_element = getLastElement(current_block->nodes);
- while((current_nd_element != NULL) && (usedVars != NULL))
- {
- current_node = (t_cflow_Node *) LDATA(current_nd_element);
- /* test if we have to insert a store */
- if ( (current_node->uses[0] != NULL)
- && ((current_node->uses[0])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[0]) != NULL)
- {
- usedVars = _insertStore(program, graph, current_block
- , current_node, current_node->uses[0], usedVars);
- }
- }
- /* test if we have to insert a store */
- if ( (current_node->uses[1] != NULL)
- && ((current_node->uses[1])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[1]) != NULL)
- {
- usedVars = _insertStore(program, graph, current_block
- , current_node, current_node->uses[1], usedVars);
- }
- }
- /* test if we have to insert a store */
- if ( (current_node->uses[2] != NULL)
- && ((current_node->uses[2])->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->uses[2]) != NULL)
- {
- usedVars = _insertStore(program, graph, current_block
- , current_node, current_node->uses[2], usedVars);
- }
- }
- /* test if we have to insert a store */
- if ( (current_node->def != NULL)
- && ((current_node->def)->ID != REG_0) )
- {
- if (findElement(usedVars, current_node->def) != NULL)
- {
- usedVars = _insertStore(program, graph, current_block
- , current_node, current_node->def, usedVars);
- }
- }
-
- /* retrieve the previous element */
- current_nd_element = LPREV(current_nd_element);
- }
- current_bb_element = LNEXT(current_bb_element);
- }
- /* free the list `usedVars' */
- freeList(usedVars);
-
- return graph;
- }
- void updatCflowInfos(t_program_infos *program, t_cflow_Graph *graph
- , t_reg_allocator *RA, t_list *label_bindings)
- {
- t_list *current_bb_element;
- t_basic_block *current_block;
- t_axe_instruction *current_instr;
- t_list *current_nd_element;
- t_cflow_Node *current_node;
- int current_row;
- int found;
-
- /* preconditions */
- assert(program != NULL);
- assert(graph != NULL);
- assert(RA != NULL);
-
- /* initialize local variables */
- current_row = 0;
- found = 0;
-
- current_bb_element = graph->blocks;
- while (current_bb_element != NULL)
- {
- int counter;
- int assignedRegisters[RA_MIN_REG_NUM][3];
- current_block = (t_basic_block *) LDATA(current_bb_element);
- assert(current_block != NULL);
- /* initialize used_Registers */
- for (counter = 0; counter < RA_MIN_REG_NUM; counter ++)
- {
- assignedRegisters[counter][0] = REG_INVALID; /* invalid register */
- assignedRegisters[counter][1] = 0; /* need write back */
- assignedRegisters[counter][2] = 0; /* currently used */
- }
- /* retrieve the list of nodes for the current basic block */
- current_nd_element = current_block->nodes;
- while(current_nd_element != NULL)
- {
- int used_Registers[3] = {-1, -1, -1};
- /* retrieve the data associated with the current node of the block */
- current_node = (t_cflow_Node *) LDATA(current_nd_element);
- /* fetch the current instruction */
- current_instr = current_node->instr;
- /* Test if a requested variable is already loaded into a register */
- if (current_instr->reg_1 != NULL)
- {
- if (RA->bindings[(current_instr->reg_1)->ID]
- == RA_SPILL_REQUIRED)
- {
- int current_row = 0;
- int found = 0;
-
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][0]
- == (current_instr->reg_1)->ID)
- {
- /* update the value of used_Register */
- used_Registers[0] = current_row;
- /* update the value of `assignedRegisters` */
- /* set currently used flag */
- assignedRegisters[current_row][2] = 1;
- /* test if a write back is needed */
- if (! (current_instr->reg_1)->indirect)
- {
- /* if the current instruction is a STORE we don't need
- * to write back the value of reg_1 again in memory. */
- /* Also if the current instruction is a WRITE instruction
- * we don't have to set the flag "dirty" for the
- * register assignedRegisters[current_row], since reg_1
- * is "used" but not "defined" */
- if ( (current_instr->opcode != STORE)
- && (current_instr->opcode != AXE_WRITE) )
- {
- assignedRegisters[current_row][1] = 1;
- }
- /* if the current instruction is a STORE we have to
- * notify that the write back is happened by
- * resetting the flag "dirty" */
- if (current_instr->opcode == STORE)
- assignedRegisters[current_row][1] = 0;
- }
- /* notify that the value was found */
- found = 1;
- }
- current_row ++;
- }
- }
- }
- if (current_instr->reg_2 != NULL)
- {
- if (RA->bindings[(current_instr->reg_2)->ID]
- == RA_SPILL_REQUIRED)
- {
- int current_row = 0;
- int found = 0;
-
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][0]
- == (current_instr->reg_2)->ID)
- {
- /* update the value of used_Register */
- used_Registers[1] = current_row;
- /* update the value of `assignedRegisters` */
- /* set currently used flag */
- assignedRegisters[current_row][2] = 1;
- /* notify that the value was found */
- found = 1;
- }
-
- current_row ++;
- }
- }
- }
- if (current_instr->reg_3 != NULL)
- {
- if (RA->bindings[(current_instr->reg_3)->ID]
- == RA_SPILL_REQUIRED)
- {
- int current_row = 0;
- int found = 0;
-
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][0]
- == (current_instr->reg_3)->ID)
- {
- /* update the value of used_Register */
- used_Registers[2] = current_row;
- /* update the value of `assignedRegisters` */
- /* set currently used flag */
- assignedRegisters[current_row][2] = 1;
- /* notify that the value was found */
- found = 1;
- }
-
- current_row ++;
- }
- }
- }
- /* phase two */
- if (current_instr->reg_2 != NULL)
- {
- if ((RA->bindings[(current_instr->reg_2)->ID]
- == RA_SPILL_REQUIRED) && (used_Registers[1] == -1))
- {
- int current_row = 0;
- int found = 0;
-
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][2] == 0)
- {
- int register_found = current_row + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
-
- if (assignedRegisters[current_row][1] == 1)
- {
- /* NEED WRITE BACK */
- _insertStoreSpill(program, assignedRegisters[current_row][0]
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- }
- _insertLoadSpill(program, (current_instr->reg_2)->ID
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- /* update the control informations */
- assignedRegisters[current_row][0] = (current_instr->reg_2)->ID;
- assignedRegisters[current_row][1] = 0;
- assignedRegisters[current_row][2] = 1;
- used_Registers[1] = current_row;
- found = 1;
- }
-
- current_row ++;
- }
- assert(found != 0);
- }
- }
- if (current_instr->reg_3 != NULL)
- {
- if ((RA->bindings[(current_instr->reg_3)->ID]
- == RA_SPILL_REQUIRED) && (used_Registers[2] == -1))
- {
- int current_row = 0;
- int found = 0;
- if ((current_instr->reg_3)->ID == (current_instr->reg_2)->ID)
- {
- used_Registers[2] = used_Registers[1];
- found = 1;
- }
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][2] == 0)
- {
- int register_found = current_row + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
-
- if (assignedRegisters[current_row][1] == 1)
- {
- /* NEED WRITE BACK */
- _insertStoreSpill(program, assignedRegisters[current_row][0]
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- }
- _insertLoadSpill(program, (current_instr->reg_3)->ID
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- /* update the control informations */
- assignedRegisters[current_row][0] = (current_instr->reg_3)->ID;
- assignedRegisters[current_row][1] = 0;
- assignedRegisters[current_row][2] = 1;
- used_Registers[2] = current_row;
-
- found = 1;
- }
-
- current_row ++;
- }
- }
- }
- if (current_instr->reg_1 != NULL)
- {
- if ((RA->bindings[(current_instr->reg_1)->ID]
- == RA_SPILL_REQUIRED) && (used_Registers[0] == -1))
- {
- int current_row = 0;
- int found = 0;
-
- while ((current_row < RA_MIN_REG_NUM) && !found)
- {
- if (assignedRegisters[current_row][2] == 0)
- {
- int register_found = current_row + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
-
- if (assignedRegisters[current_row][1] == 1)
- {
- /* NEED WRITE BACK */
- _insertStoreSpill(program, assignedRegisters[current_row][0]
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- }
- /* test if we need to load the value from register */
- if ( (current_instr->reg_1)->indirect
- || (current_instr->opcode == AXE_WRITE))
- {
- _insertLoadSpill(program, (current_instr->reg_1)->ID
- , register_found, graph, current_block
- , current_node, label_bindings, 1);
- }
- /* update the control informations */
- assignedRegisters[current_row][0] = (current_instr->reg_1)->ID;
-
- if (! (current_instr->reg_1)->indirect)
- {
- if ( (current_instr->opcode != STORE)
- && (current_instr->opcode != AXE_WRITE) )
- {
- assignedRegisters[current_row][1] = 1;
- }
- if (current_instr->opcode == STORE)
- assignedRegisters[current_row][1] = 0;
- }
- assignedRegisters[current_row][2] = 1;
- used_Registers[0] = current_row;
-
- found = 1;
- }
-
- current_row ++;
- }
- assert(found != 0);
- }
- }
-
- /* update the instruction informations */
- if (current_instr->reg_1 != NULL)
- {
- if (used_Registers[0] != -1)
- {
- current_instr->reg_1->ID = used_Registers[0] + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
- assignedRegisters[used_Registers[0]][2] = 0;
- }
- else
- current_instr->reg_1->ID =
- RA->bindings[(current_instr->reg_1)->ID];
- }
- if (current_instr->reg_2 != NULL)
- {
- if (used_Registers[1] != -1)
- {
- current_instr->reg_2->ID = used_Registers[1] + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
- assignedRegisters[used_Registers[1]][2] = 0;
- }
- else
- current_instr->reg_2->ID =
- RA->bindings[(current_instr->reg_2)->ID];
- }
- if (current_instr->reg_3 != NULL)
- {
- if (used_Registers[2] != -1)
- {
- current_instr->reg_3->ID = used_Registers[2] + NUM_REGISTERS
- + 1 - RA_MIN_REG_NUM;
- assignedRegisters[used_Registers[2]][2] = 0;
- }
- else
- current_instr->reg_3->ID =
- RA->bindings[(current_instr->reg_3)->ID];
- }
- /* retrieve the previous element */
- current_nd_element = LNEXT(current_nd_element);
- }
- /* initialize used_Registers */
- for (counter = 0; counter < RA_MIN_REG_NUM; counter ++)
- {
- if (assignedRegisters[counter][1] == 1)
- {
- /* NEED WRITE BACK */
- _insertStoreSpill(program, assignedRegisters[counter][0]
- , (counter + NUM_REGISTERS + 1 - RA_MIN_REG_NUM)
- , graph, current_block
- , current_node, label_bindings, 1);
- }
- }
-
- /* retrieve the next basic block element */
- current_bb_element = LNEXT(current_bb_element);
- }
- }
- int _insertStoreSpill(t_program_infos *program, int temp_register, int selected_register
- , t_cflow_Graph *graph, t_basic_block *current_block
- , t_cflow_Node *current_node, t_list *labelBindings, int before)
- {
- t_axe_instruction *storeInstr;
- t_axe_instruction *current_instr;
- t_cflow_Node *storeNode;
- t_list *elementFound;
- t_tempLabel pattern;
- t_tempLabel *tlabel;
- /* initialize current_instr */
- current_instr = current_node->instr;
- pattern.regID = temp_register;
- elementFound = CustomfindElement (labelBindings
- , &pattern, compareTempLabels);
- if (elementFound == NULL) {
- finalizeNode(storeNode);
- errorcode = AXE_TRANSFORM_ERROR;
- return -1;
- }
- tlabel = (t_tempLabel *) LDATA(elementFound);
- assert(tlabel != NULL);
- /* create a store instruction */
- storeInstr = _createUnary (program
- , selected_register, tlabel->labelID, STORE);
- /* test if an error occurred */
- if (errorcode != AXE_OK) {
- free_Instruction(storeInstr);
- return -1;
- }
- /* create a node for the load instruction */
- storeNode = allocNode (graph, storeInstr);
- if (cflow_errorcode != CFLOW_OK) {
- finalizeNode(storeNode);
- free_Instruction(storeInstr);
- errorcode = AXE_TRANSFORM_ERROR;
- return -1;
- }
- /* test if we have to insert the node `storeNode' before `current_node'
- * inside the basic block */
- if (before == 0)
- insertNodeAfter(current_block, current_node, storeNode);
- else
- insertNodeBefore(current_block, current_node, storeNode);
-
- return 0;
- }
- int _insertLoadSpill(t_program_infos *program, int temp_register, int selected_register
- , t_cflow_Graph *graph, t_basic_block *block
- , t_cflow_Node *current_node, t_list *labelBindings, int before)
- {
- t_axe_instruction *loadInstr;
- t_axe_instruction *current_instr;
- t_cflow_Node *loadNode;
- t_list *elementFound;
- t_tempLabel pattern;
- t_tempLabel *tlabel;
- /* initialize current_instr */
- current_instr = current_node->instr;
- pattern.regID = temp_register;
- elementFound = CustomfindElement (labelBindings
- , &pattern, compareTempLabels);
- if (elementFound == NULL) {
- finalizeNode(loadNode);
- errorcode = AXE_TRANSFORM_ERROR;
- return -1;
- }
- tlabel = (t_tempLabel *) LDATA(elementFound);
- assert(tlabel != NULL);
-
- /* create a load instruction */
- loadInstr = _createUnary (program
- , selected_register, tlabel->labelID, LOAD);
- /* test if an error occurred */
- if (errorcode != AXE_OK) {
- free_Instruction(loadInstr);
- finalizeNode(loadNode);
- return -1;
- }
- /* update the value of storeInstr and instr */
- (loadInstr->reg_1)->ID = selected_register;
- /* create a node for the load instruction */
- loadNode = allocNode (graph, loadInstr);
- /* test if an error occurred */
- if (cflow_errorcode != CFLOW_OK) {
- finalizeNode(loadNode);
- free_Instruction(loadInstr);
- errorcode = AXE_TRANSFORM_ERROR;
- return -1;
- }
- if ((current_node->instr)->labelID != NULL)
- {
- /* modify the label informations */
- loadInstr->labelID = (current_node->instr)->labelID;
- (current_node->instr)->labelID = NULL;
- }
-
- if (before == 1)
- /* insert the node `loadNode' before `current_node' */
- insertNodeBefore(block, current_node, loadNode);
- else
- insertNodeAfter(block, current_node, loadNode);
- return 0;
- }
|