/* *************************************************************************************************************** * createCallStack: * fun: The ASTNode of the function for which call stack has to pushed into the stack. * This function subtracts the width of the function(which includes the temporaries too) from the current * stack pointer. Thus creating space for local and temporaries in the call stack. **************************************************************************************************************** */ void createCallStack(ASTNode* fun){ FunctionNode* funNode = (FunctionNode*)malloc(sizeof(FunctionNode)); funNode->funTok = fun->token; funNode = ((FunctionNode*)get(FUNCTION_TABLE.hashTable,funNode)); generate(createInstruction(SUB,RSP,IMM,0,0,funNode->width+funNode->tempCount)); if(GLOBAL_WIDTH!=0){ InstructionList* globalIns = createInstruction(MOV,RCX,-1,-1,-1,-1); strcpy(globalIns->label,data[GLOBAL]); generate(globalIns); } }
//Screens are always stored in the data folder. //However, the FileIO object passed has all the necessary information. void ScreenType::parseScreenFile(FileIO* file) { std::string tempInput; std::vector <std::string> parserOutput; //file -> textOpenFile(screenFileName, false); //No longer needed. stringFunc stringParcer; if (file -> readLine(&tempInput)){ parserOutput = stringParcer.parseAllTokens(tempInput, "\\"); } else { //Wut? Broken } botX = atoi(parserOutput.at(0).c_str()); botY = atoi(parserOutput.at(1).c_str()); topX = atoi(parserOutput.at(2).c_str()); topY = atoi(parserOutput.at(3).c_str()); screenID = parserOutput.at(4); while (file -> readLine(&tempInput)){ //Empty lines are skipped. if (tempInput.empty()){ continue; } //Lines with a pound at the beginning are ignored, these are comments. if (tempInput.at(0) == '#'){ //cout << "Read comment: " << tempInput << endl; continue; } if (createInstruction(tempInput)){ //cout << tempInput << endl; continue; } //Something bad happened. } isGood = true; file -> closeFile(); }
void loadInstructions(instruction *instru, char * location) { int n; FILE * file; file = fopen(location,"r"); char buffer[10]; fgets ( buffer, sizeof buffer, file ); n = atoi(buffer); int i; createInstruction(instru,n); for(i=0;i<n;i++) { fgets ( buffer, sizeof buffer, file ); strcpy(instru->data[i],buffer); } fclose(file); }
/* ***************************************************************************************************************** * codeGenerator: * child : The ASTNode for which the code has to be generated. * funInfo : This has the FunctionNode(see astDef.h for details) for the function * which has the 'child'. * currLabel : Possible label which can be assigned to the current instruction. * parentLabel : The label of the parent node in AST. * This function simply does the post order traversal of a function and generates code for that function. * In our case it works only for the main function. ***************************************************************************************************************** */ void codeGenerator(ASTNode* child,FunctionNode* funInfo,Label* currLabel, int parentLabel){ if(child==NULL){ return; } int tempCount = funInfo->width; int tempLabel = currLabel->labelNum; InstructionList* funLabel = NULL; ASTNode* ifChild = NULL; int ifFlag=0; TokenName tokenName = child->token->tokenName; switch(tokenName){ case TK_MAIN: funLabel = createLabel(1,0); strcpy(funLabel->label,"main"); generate(funLabel); createCallStack(child); break; case TK_ASSIGNOP: generateArithmeticExpression(child,funInfo->funTok,&tempCount); break; case TK_IF: currLabel->labelNum += 2; generateBooleanExpression(child->child,funInfo->funTok,addLabel(1,tempLabel),addLabel(0,tempLabel),currLabel,&tempCount); generate(createLabel(1,tempLabel)); break; case TK_ELSE: generate(createInstruction(JMP,-1,-1,parentLabel+1,1,0)); generate(createLabel(0,parentLabel)); break; case TK_READ: generateScanf(child->child,funInfo); break; case TK_WRITE: generatePrintf(child->child,funInfo); break; case TK_WHILE: generate(createLabel(1,currLabel->labelNum)); currLabel->labelNum += 2; generateBooleanExpression(child->child,funInfo->funTok,addLabel(1,tempLabel+1),addLabel(0,tempLabel),currLabel,&tempCount); generate(createLabel(1,tempLabel+1)); break; } if(tokenName==TK_IF) codeGenerator(child->child,funInfo,currLabel, tempLabel); else codeGenerator(child->child,funInfo,currLabel, parentLabel); switch(tokenName){ case TK_MAIN: generate(createInstruction(ADD,RSP,IMM,0,0,funInfo->width+funInfo->tempCount)); generate(createInstruction(RET,-1,-1,-1,-1,-1)); break; case TK_WHILE: generate(createInstruction(JMP,-1,-1,tempLabel,1,0)); generate(createLabel(0,tempLabel)); break; case TK_IF: generate(createLabel(1,tempLabel+1)); ifChild = child->child; while(ifChild!=NULL){ if(ifChild->token->tokenName==TK_ELSE){ ifFlag = 1; break; } ifChild = ifChild->next; } if(!ifFlag) generate(createLabel(0,tempLabel)); break; } codeGenerator(child->next,funInfo,currLabel, parentLabel); }
/* ***************************************************************************************************************** * generatePrintf: * child : The ASTNode of the id which has to be printed. * funInfo : This has the FunctionNode(see astDef.h for details) for the function * which has the 'write' function. * This function simply creates instruction to write the identifier specified. * It handles record types too. ***************************************************************************************************************** */ void generatePrintf(ASTNode* child,FunctionNode* funInfo){ int localOffset = 0; if(child->token->tokenName==TK_ID){ ASTNode* field = NULL; if(child->child!=NULL){ field = child->child; } VariableNode* var = createVarNode(child->token,funInfo->funTok,NULL,INT,0,&localOffset); VariableNode* freeVar = var; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); if(var==NULL){ var = freeVar; var->isGlobal = 1; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); } free(freeVar); if(var->type==RECORD && field!=NULL){ FieldList* head = var->recordPtr->fields; int tempOffset = var->offset; for(;head!=NULL;tempOffset+=head->width,head=head->next){ if(strcmp(field->token->lexemeName,head->token->lexemeName)==0){ generate(createInstruction(MOV,RSI,IMM,0,0,0)); generate(createInstruction(MOV,ESI,MEM,tempOffset,var->isGlobal,0)); InstructionList* label = createInstruction(MOV,RDI,-1,-1,-1,-1); strcpy(label->label,data[FORMAT_OUT_NEWLINE]); generate(label); generate(createInstruction(PUSH,RAX,NONE,0,0,0)); generate(createInstruction(PUSH,RCX,NONE,0,0,0)); generate(createInstruction(MOV,RAX,IMM,0,0,0)); InstructionList* call = createInstruction(CALL,-1,-1,-1,-1,-1); strcpy(call->label,"printf"); generate(call); generate(createInstruction(POP,RCX,NONE,0,0,0)); generate(createInstruction(POP,RAX,NONE,0,0,0)); } } } else if(var->type==RECORD){ FieldList* head = var->recordPtr->fields; int tempOffset = var->offset; for(;head!=NULL;tempOffset+=head->width,head=head->next){ generate(createInstruction(MOV,RSI,IMM,0,0,0)); generate(createInstruction(MOV,ESI,MEM,tempOffset,var->isGlobal,0)); InstructionList* label = createInstruction(MOV,RDI,-1,-1,-1,-1); strcpy(label->label,data[FORMAT_OUT_SPACE]); generate(label); generate(createInstruction(PUSH,RAX,NONE,0,0,0)); generate(createInstruction(PUSH,RCX,NONE,0,0,0)); generate(createInstruction(MOV,RAX,IMM,0,0,0)); InstructionList* call = createInstruction(CALL,-1,-1,-1,-1,-1); strcpy(call->label,"printf"); generate(call); generate(createInstruction(POP,RCX,NONE,0,0,0)); generate(createInstruction(POP,RAX,NONE,0,0,0)); } } else{ generate(createInstruction(MOV,RSI,IMM,0,0,0)); generate(createInstruction(MOV,ESI,MEM,var->offset,var->isGlobal,0)); InstructionList* label = createInstruction(MOV,RDI,-1,-1,-1,-1); strcpy(label->label,data[FORMAT_OUT_NEWLINE]); generate(label); generate(createInstruction(PUSH,RAX,NONE,0,0,0)); generate(createInstruction(PUSH,RCX,NONE,0,0,0)); generate(createInstruction(MOV,RAX,IMM,0,0,0)); InstructionList* call = createInstruction(CALL,-1,-1,-1,-1,-1); strcpy(call->label,"printf"); generate(call); generate(createInstruction(POP,RCX,NONE,0,0,0)); generate(createInstruction(POP,RAX,NONE,0,0,0)); } } }
/* ***************************************************************************************************************** * generateBooleanExpression: * child : The ASTNode of the expression for which code has to be generated. * funTok : This has the Token(see lexerDef.h for Token details) for the function * which has the expression. * trueLabel : The code will jump to this label if the current subtree represented * by 'child' evaluates to true. * falseLabel : The code will jump to this label if the current subtree represented * by 'child' evaluates to false. * tempCount : This is the total space occupied by all the temporary variables used while generating * code for the given boolean expression. * This function recurses and creates the code for left and right subtree of the expression and then combines * them. ***************************************************************************************************************** */ VariableNode* generateBooleanExpression(ASTNode* child,Token* funTok,Label* trueLabel,Label* falseLabel,Label* currLabel,int* tempCount){ int localOffset = 0; if(child->token->tokenName==TK_ID){ ASTNode* field = NULL; if(child->child!=NULL){ field = child->child; } VariableNode* var = createVarNode(child->token,funTok,NULL,INT,0,&localOffset); VariableNode* freeVar = var; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); if(var==NULL){ var = freeVar; var->isGlobal = 1; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); } free(freeVar); if(var->type==RECORD && field!=NULL){ FieldList* head = var->recordPtr->fields; for(;head!=NULL;head=head->next){ if(strcmp(field->token->lexemeName,head->token->lexemeName)==0){ return createVarNode(NULL,funTok,NULL,head->type,0,&localOffset); } } } return var; } if(child->token->tokenName==TK_NOT){ VariableNode* notVariable = generateBooleanExpression(child->child,funTok,falseLabel,trueLabel,currLabel,tempCount); return NULL; } ASTNode* leftChild = child->child; ASTNode* rightChild = leftChild->next; Type leftType=-1,rightType=-1; VariableNode* leftNode = NULL; VariableNode* rightNode = NULL; if(leftChild!=NULL){ leftType = (leftChild->token->tokenName==TK_NUM)? INT:-1; leftType = (leftChild->token->tokenName==TK_RNUM)?REAL:leftType; } if(rightChild!=NULL){ rightType = (rightChild->token->tokenName==TK_NUM)?INT:-1; rightType = (rightChild->token->tokenName==TK_RNUM)?REAL:rightType; } if(leftType!=-1){ generate(createInstruction(MOV,MEM,IMM,*tempCount,0,leftChild->token->value.intValue)); leftNode = createVarNode(NULL,funTok,NULL,leftType,0,tempCount); } if(rightType!=-1){ generate(createInstruction(MOV,MEM,IMM,*tempCount,0,rightChild->token->value.intValue)); rightNode = createVarNode(NULL,funTok,NULL,rightType,0,tempCount); } if(child->token->tokenName==TK_AND){ Label* ANDLabel = addLabel(1,currLabel->labelNum); currLabel->labelNum = currLabel->labelNum +1; currLabel->labelType = 1; generateBooleanExpression(leftChild,funTok,ANDLabel,falseLabel,currLabel,tempCount); generate(createLabel(1,ANDLabel->labelNum)); generateBooleanExpression(rightChild,funTok, trueLabel, falseLabel, currLabel,tempCount); return NULL; } if(child->token->tokenName==TK_OR){ Label* ORLabel = addLabel(0,currLabel->labelNum); currLabel->labelNum = currLabel->labelNum +1; currLabel->labelType = 0; generateBooleanExpression(leftChild,funTok,trueLabel,ORLabel, currLabel,tempCount); generate(createLabel(0,ORLabel->labelNum)); generateBooleanExpression(rightChild,funTok, trueLabel, falseLabel, currLabel,tempCount); return NULL; } if(leftNode==NULL){ leftNode = generateBooleanExpression(leftChild,funTok,trueLabel,falseLabel,currLabel,tempCount); } if(rightNode==NULL){ rightNode = generateBooleanExpression(rightChild,funTok,trueLabel,falseLabel,currLabel,tempCount); } switch(child->token->tokenName){ case TK_LT: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JL,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JGE,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; case TK_GT: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JG,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JLE,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; case TK_LE: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JLE,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JG,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; case TK_GE: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JGE,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JL,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; case TK_EQ: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JE,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JNE,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; case TK_NE: generate(createInstruction(MOV,EAX,MEM,leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(CMP,EAX,MEM,rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(JNE,-1,-1,trueLabel->labelNum,trueLabel->labelType,0)); generate(createInstruction(JE,-1,-1,falseLabel->labelNum,falseLabel->labelType,0)); break; } return NULL; }
/* ***************************************************************************************************************** * generateArithmeticExpression: * child : The ASTNode of the expression for which code has to be generated. * funTok : This has the Token(see lexerDef.h for Token details) for the function * which has the expression. * tempCount : This is the total space occupied by all the temporary variables used while generating * code for the given arithmetic expression. * This function recurses and creates the code for left and right subtree of the expression and then combines * them. ***************************************************************************************************************** */ VariableNode* generateArithmeticExpression(ASTNode* child,Token* funTok,int *tempCount){ int localOffset = 0; if(child->token->tokenName==TK_ID){ ASTNode* field = NULL; if(child->child!=NULL){ field = child->child; } VariableNode* var = createVarNode(child->token,funTok,NULL,INT,0,&localOffset); VariableNode* freeVar = var; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); if(var==NULL){ var = freeVar; var->isGlobal = 1; var = (VariableNode*)get(SYMBOL_TABLE.hashTable,var); } free(freeVar); if(var->type==RECORD && field!=NULL){ FieldList* head = var->recordPtr->fields; int recordOffset = var->offset; for(;head!=NULL;head=head->next){ if(strcmp(field->token->lexemeName,head->token->lexemeName)==0){ return createVarNode(NULL,funTok,NULL,head->type,0,&recordOffset); } recordOffset += head->width; } } return var; } ASTNode* leftChild = child->child; ASTNode* rightChild = leftChild->next; Type leftType=-1,rightType=-1; VariableNode* leftNode = NULL; VariableNode* rightNode = NULL; leftType = (leftChild->token->tokenName==TK_NUM)? INT:-1; leftType = (leftChild->token->tokenName==TK_RNUM)?REAL:leftType; rightType = (rightChild->token->tokenName==TK_NUM)?INT:-1; rightType = (rightChild->token->tokenName==TK_RNUM)?REAL:rightType; if(leftType!=-1){ generate(createInstruction(MOV,MEM,IMM,*tempCount,0,leftChild->token->value.intValue)); leftNode = createVarNode(NULL,funTok,NULL,leftType,0,tempCount); } if(rightType!=-1){ generate(createInstruction(MOV,MEM,IMM,*tempCount,0,rightChild->token->value.intValue)); rightNode = createVarNode(NULL,funTok,NULL,rightType,0,tempCount); } if( child->token->tokenName==TK_PLUS|| child->token->tokenName==TK_MINUS|| child->token->tokenName==TK_MUL|| child->token->tokenName==TK_DIV|| child->token->tokenName==TK_ASSIGNOP ){ if(leftType==-1) leftNode = generateArithmeticExpression(leftChild,funTok,tempCount); if(rightType==-1) rightNode = generateArithmeticExpression(rightChild,funTok,tempCount); if(leftType==-1 && leftNode!=NULL) leftType = leftNode->type; if(rightType==-1 && rightNode!=NULL) rightType = rightNode->type; } if(child->token->tokenName==TK_ASSIGNOP){ if(leftType!=RECORD){ generate(createInstruction(MOV, EAX, MEM, rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, leftNode->offset,leftNode->isGlobal,0)); } else{ FieldList* field = leftNode->recordPtr->fields; int leftRecordOffset = leftNode->offset; int rightRecordOffset = rightNode->offset; for(;field!=NULL;field=field->next){ generate(createInstruction(MOV, EAX, MEM, rightRecordOffset,rightNode->isGlobal,0)); //int temp = leftRecordOffset; generate(createInstruction(MOV, MEM, EAX, leftRecordOffset,leftNode->isGlobal,0)); rightRecordOffset+=(field->width); leftRecordOffset+=field->width; //leftRecordOffset = temp + field->width; } return NULL; } } if(leftType==rightType && leftType!=RECORD){ switch(child->token->tokenName){ case TK_PLUS: generate(createInstruction(MOV, EAX, MEM, leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(ADD, EAX, MEM, rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); break; case TK_MINUS: generate(createInstruction(MOV, EAX, MEM, leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(SUB, EAX, MEM, rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); break; case TK_MUL: generate(createInstruction(MOV, EAX, MEM, leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(IMUL, MEM, NONE, rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); break; case TK_DIV: generate(createInstruction(MOV, EAX, MEM, leftNode->offset,leftNode->isGlobal,0)); generate(createInstruction(MOV, EDX, IMM, 0,0,0)); generate(createInstruction(IDIV, MEM, NONE, rightNode->offset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); break; } localOffset = *tempCount; *tempCount = *tempCount + ((leftType==INT)?INT_WIDTH:REAL_WIDTH); return createVarNode(NULL,funTok,NULL,leftType,0,&localOffset); } else if(leftType==rightType){ int leftRecordOffset = leftNode->offset; int rightRecordOffset = rightNode->offset; FieldList* field = leftNode->recordPtr->fields; localOffset = *tempCount; switch(child->token->tokenName){ case TK_PLUS: for(;field!=NULL;field=field->next){ generate(createInstruction(MOV, EAX, MEM, leftRecordOffset,leftNode->isGlobal,0)); generate(createInstruction(ADD, EAX, MEM, rightRecordOffset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); leftRecordOffset+=field->width; rightRecordOffset+=field->width; *tempCount += field->width; } break; case TK_MINUS: for(;field!=NULL;field=field->next){ generate(createInstruction(MOV, EAX, MEM, leftRecordOffset,leftNode->isGlobal,0)); generate(createInstruction(SUB, EAX, MEM, rightRecordOffset,rightNode->isGlobal,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); leftRecordOffset+=field->width; rightRecordOffset+=field->width; *tempCount += field->width; } break; } return createVarNode(NULL,funTok,leftNode->recordPtr->recTok,leftType,0,&localOffset); } else{ int recordOffset = (leftType==INT||leftType==REAL)?rightNode->offset:leftNode->offset; int scalarOffset = (leftType==INT||leftType==REAL)?leftNode->offset:rightNode->offset; int isGlobal = (leftType==INT||leftType==REAL)?rightNode->isGlobal:leftNode->isGlobal; FieldList* field = (leftType==INT||leftType==REAL)?rightNode->recordPtr->fields:leftNode->recordPtr->fields; RecordNode* recordPtr = (leftType==INT||leftType==REAL)?rightNode->recordPtr:leftNode->recordPtr; localOffset = *tempCount; switch(child->token->tokenName){ case TK_MUL: for(;field!=NULL;field=field->next){ generate(createInstruction(MOV, EAX, MEM, recordOffset,isGlobal,0)); generate(createInstruction(IMUL, MEM, NONE, scalarOffset,0,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount,0,0)); recordOffset+=field->width; *tempCount += field->width; } break; case TK_DIV: for(;field!=NULL;field=field->next){ generate(createInstruction(MOV, EAX, MEM, recordOffset, isGlobal,0)); generate(createInstruction(MOV, EDX, IMM, 0,0,0)); generate(createInstruction(IDIV, MEM, NONE, scalarOffset,0,0)); generate(createInstruction(MOV, MEM, EAX, *tempCount, 0,0)); recordOffset+=field->width; *tempCount += field->width; } break; } return createVarNode(NULL,funTok,recordPtr->recTok,leftType,0,&localOffset); } }
/* *************************************************************************************************************** * createLabel: * labelType: This represents the type of label (0 or 1). 0---> F(False label) 1--->T(True label). * labelNum : This gives a number to the label. * This function is used to create labels in the code.The labels are of form T<labelNum> or F<labelNum>. * It stores labels in form of three address code i.e. Instruction List type. **************************************************************************************************************** */ InstructionList* createLabel(int labelType,int labelNum){ InstructionList* newIns = createInstruction(-1,-1,-1,-1,-1,-1); newIns->isLabel = 1; (labelType)? sprintf(newIns->label,"T%d",labelNum):sprintf(newIns->label,"F%d",labelNum); return newIns; }
/* ------------------------------------------------------------------------------------------ */ void checkInstruction(ins *p){ reg *rz=NULL; reg *rx=NULL; reg *ry=NULL; reg *rt=NULL; // temporary register (may or not be used) ins *ip=NULL; // auxiliary instruction pointer (for other registers) ins *ti=NULL; // temporary instruction pointer (to be used with the temporary register) ins *mi=NULL; // main instruction pointer (used with the final instruction) /* * >> input: rz = rx <op> ry * * * rx = ARP + lookup(rx->value) * rx = * rx * ry = ARP + lookup(ry->value) * ry = * ry * rt = rx <op> ry * rz = ARP + lookup(rz->value) * *rz = rt */ if(p == NULL) return; #ifdef VERBOSE printf("\n"); table_print(registers); printf("[checkInstruction] "); printInstruction(p); #endif // :: -------------------------------- :: THE ALGORITHM :: // 1st step: ensure that 'rx' and 'ry' have register // -- // checking 'rx' if((p->src1[0] != '\0') && !isNumeric(p->src1)){ rx=reg_search(p->src1); if(rx==NULL){ // allocates register rx=reg_ensure(p->src1); if(isVar(p->src1)){ // loading the local variable from memory load(p->src1); ip = createInstruction(idx++); copy(ip->dst, rx->name); ip->arp=true; ip->offset=lookup(p->src1); append(ip); ip = createInstruction(idx++); copy(ip->dst, rx->name); ip->ops1='*'; copy(ip->src1, rx->name); append(ip); } if(rx!=NULL){ // set properties for register rx->dist=distance(p, rx->value); rx->dirty=false; } } } else rx=NULL; // checking 'ry' if((p->src2[0] != '\0') && !isNumeric(p->src2)){ ry=reg_search(p->src2); if(ry==NULL){ // allocates register ry=reg_ensure(p->src2); if(isVar(p->src2)){ // loading the local variable 'ry' from memory load(p->src2); // loading the local variable 'ry' from memory ip = createInstruction(idx++); copy(ip->dst, ry->name); ip->arp=true; ip->offset=lookup(p->src2); append(ip); ip = createInstruction(idx++); copy(ip->dst, ry->name); ip->ops1='*'; copy(ip->src1, ry->name); append(ip); } if(ry!=NULL){ // set properties for register ry->dist=distance(p, ry->value); ry->dirty=true; } } } else ry=NULL; // 2nd step: allocate the 'rt' temporary register; creates the 'ti' temporary instruction // -- ti = createInstruction(idx++); // get 'rx' if(isNumeric(p->src1)) copy(ti->src1, p->src1); // found a constant else if(rx!=NULL) copy(ti->src1, rx->name); // got the 'rx' // get the operator ti->ops2=p->ops2; // get 'ry' if(isNumeric(p->src2)) copy(ti->src2, p->src2); // found a constant else if(ry!=NULL) copy(ti->src2, ry->name); // got the 'ry' if((p->dst[0] != '\0') && !isNumeric(p->dst)){ // allocate the 'rt' register ("r0" by default) rt=reg_search("store"); // rt=reg_get(); if(rt!=NULL) rt->dirty=false; } else rt=NULL; // this could lead to an error if(rt!=NULL) copy(ti->dst, rt->name); append(ti); // 3rd step: frees if possible frees 'rx' and 'ry' // -- // free 'rx' if((rx!=NULL) && (rx->dist==MAXDIST || rx->dist==-2)) reg_free(rx); // free 'ry' if((ry!=NULL) && (ry->dist==MAXDIST || ry->dist==-2)) reg_free(ry); // 4th step: allocate the 'rz' register and create the main instruction 'mi' // -- mi = createInstruction(idx++); // allocate the 'rz' register if((p->dst[0] != '\0') && !isNumeric(p->dst)){ // store store(p->dst); rz=reg_search(p->dst); if(rz==NULL){ // allocates register rz=reg_ensure(p->dst); if(isVar(p->dst)){ // loads the local variable for store operation ip = createInstruction(idx++); copy(ip->dst, rz->name); ip->arp=true; ip->offset=lookup(p->dst); append(ip); } if(rz!=NULL){ // set properties for register rz->dist=distance(p, rz->value); rz->dirty=false; } } } else rz=NULL; // this would be an error if(rz!=NULL) copy(mi->dst, rz->name); if(rt!=NULL) copy(mi->src1, rt->name); if(isVar(p->dst)) mi->opd='*'; append(mi); // 5th step: frees 'rt'; if possible frees 'rz' // -- #ifdef VERBOSE if(rt!=NULL) printf(" [rt] store: %s :: (%s)\n", rt->name, rt->value); else printf(" [rt] is null\n"); if(rz!=NULL) printf(" [rz] store: %s :: (%s)\n", rz->name, rz->value); else printf(" [rz] is null\n"); #endif // free 'rt' if(rt!=NULL) reg_free(rt); // free 'rz' if((rz!=NULL) && (rz->dist==MAXDIST || rz->dist<0)) reg_free(rz); // 6th step: set the dirty property for the registers // -- // check 'rx' if(rx!=NULL) rx->dirty=true; // check 'ry' if(ry!=NULL) ry->dirty=true; // check 'rt' if(rt!=NULL) rt->dirty=true; // check 'rz' if(rz!=NULL) rz->dirty=false; // nota: um registo e' dirty apenas quando o seu conteudo e' manipulado na memoria !!!! // (confirmar e corrigir se necessario o 6o passo) // mudar os valores de dirty para oposto: 'false' <-> 'true' // :: -------------------------------- :: THE END :: #ifdef VERBOSE table_print(registers); printf("\n"); #endif return; }
/* ------------------------------------------------------------------------------ */ void readInstructionsFromFile(char *fname){ int i; ins *ip; FILE *fp; char tk[4]={' ', '\t', '\n', '\0'}; char str[80]; char *s1, *s2, *s3, *s4, *s5; i = 0; fp = fopen(fname,"r"); if(fp == NULL){ printf(" *** Error: Cannot open (%s) as instruction input file \n",fname); Code = NULL; return; } Code = createBasicBlock(0); while(fgets(str,79,fp) != NULL){ #ifdef DEBUG // printf("read::: %s", str); #endif s1 = (char*)strtok(str, tk); if(s1 == NULL){ break; } s2 = (char*)strtok(NULL, tk); if(s2[0] != '='){ printf(" *** Error: Could not locate '=' operator in instruction as second field of input\n"); continue; } s3 = (char*)strtok(NULL, tk); s4 = (char*)strtok(NULL, tk); if(s4 != NULL){ s5 = (char*)strtok(NULL, tk); } else { s5 = NULL; } #ifdef DEBUG // printf(" parsed::: %s %s %s %s %s\n",s1, s2, s3, s4, s5); #endif ip = createInstruction(i); if(s1[0] == '*'){ setInstructionDestOperand(ip,'*'); setInstructionDest(ip, &s1[1]); } else { setInstructionDest(ip, &s1[0]); } if((s3[0] == '*') || (s3[0] == '-')){ setInstructionSource1Operand(ip, s3[0]); setInstructionSource1(ip, &s3[1]); } else { setInstructionSource1(ip, &s3[0]); } if(s4 != NULL){ setInstructionSource2Operand(ip, s4[0]); if(s5 != NULL){ setInstructionSource2(ip, s5); } else { printf(" *** Error: Was expecting a second operand in instruction %d (remove infix operand)\n",i); setInstructionSource2Operand(ip,' '); } } appendInstruction(Code,ip); #ifdef DEBUG // printf(" ...dumping instruction::\n"); // dumpInstruction(ip); // printf("\n"); #endif i++; } #ifdef DEBUG // printf(" Read %d instructions \n",i); // printBasicBlock(Code); #endif fclose(fp); }