void emitHeader() { emitComment((char*)"C- Compiler version C-F13"); emitComment((char*)"Built: Dec 12, 2013"); emitComment((char*)"Author: Brett Papineau"); //filename conversion here emitComment2((char*)"File compiled: ", (char*)out); }
/* * Emit ASC code for a then statment as part of IF-THEN-ELSE. * Assumes the corresposding statement or matched_stat code has already * been emitted. */ void emitThenMatchedStat() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); emitComment("Bottom of an IF-THEN."); emitComment("Either THEN was executed, so GOTO,"); emitComment("or land at %s%d if 'expr' was false", LABEL_PREFIX, peekLabelStackTop(labelStack)); emitStmt(STMT_LEN, "GOTO %s%d", LABEL_PREFIX, peekLabelStackTop(labelStack) + 1); emitLabel(STMT_LEN, "%s%d", LABEL_PREFIX, peekLabelStackTop(labelStack)); }
void emitEnd() { TreeNode *temp = (TreeNode*)tab->lookup((char*)"main"); //if(temp == NULL) //{ // printf("ERROR(LINKER): Procedure main is not defined\n"); //} if(temp != NULL) { backPatchJumpToHere(0, (char*)"Jump to init [backpatch]"); emitComment((char*)"BEGIN Init"); emitRM((char*)"LD", GP, 0, GP, (char*)"Set the global pointer"); emitComment((char*)"BEGIN init of globals"); //start int gloads = goff2; SymTabEntry* intable = (SymTabEntry*)tab->firstSymTabEntry(); intable = (SymTabEntry*)tab->nextSymTabEntry(intable); //skip null //intable = (SymTabEntry*)tab->nextSymTabEntry(intable); TreeNode* tmp = (TreeNode*)tab->lookup(intable->name); while(tmp != NULL) { if(tmp->kind.decl == varK) { if(!tmp->isArray) { params = 1; codeGen(tmp); } else { emitRM2((char*)"LDC", AC, tmp->size - 1, AC3, (char*)"load size of array", tmp->attr.name); emitRM2((char*)"ST", AC, tmp->location + 1, 0, (char*)"save size of array", tmp->attr.name); } } tmp=tmp->sibling; } emitComment((char*)"END init of globals"); emitRM((char*)"LDA", FP, goff, GP, (char*)"set first frame at end of globals"); emitRM((char*)"ST", FP, 0, FP, (char*)"store old fp (point to self)"); emitRM((char*)"LDA", AC, 1, PC, (char*)"Return address in ac"); emitRM((char*)"LDA", PC, temp->location - emitSkip(0) - 1, PC, (char*)"Jump to main"); emitRO((char*)"HALT", 0, 0, 0, (char*)"DONE!"); emitComment((char*)"END Init"); } }
/* * Write generated code to file. * * Parameters: * fileName: name of the .asc file to which to write. * Return: * 0 on success, * non-zero otherwise */ int emitToFile(char *fileName) { FILE *ascfp = NULL; if (doNotEmit) { return 1; } /* open the file */ ascfp = fopen(fileName, "w"); /* append end-of-program stuff here (like a STOP) */ emitComment("End of user-defined pgram"); emitStmt(STMT_LEN, "STOP"); /* * append pre-defined ASC code here, so that it's at the bottom * of the file */ #ifndef ASC_SIMPLE emitPreDefCode(); #endif /* write the emitted code to file */ writeStmtLL(ascfp, stmts); /* close the file */ if (fclose(ascfp) != 0) { err(EXIT_FAILURE, "File IO error."); } return 0; }
/* Procedure codeGen generates code to a code * file by traversal of the syntax tree. The * second parameter (codefile) is the file name * of the code file, and is used to print the * file name as a comment in the code file */ void codeGen(TreeNode * syntaxTree, char * codefile) { char * s = (char *) malloc(strlen(codefile)+7); strcpy(s,"File: "); strcat(s,codefile); emitComment("TINY Compilation to TM Code"); emitComment(s); /* generate standard prelude */ emitComment("Standard prelude:"); emitRM("LD",mp,0,ac,"load maxaddress from location 0"); emitRM("ST",ac,0,ac,"clear location 0"); emitComment("End of standard prelude."); /* generate code for TINY program */ cGen(syntaxTree); /* finish */ emitComment("End of execution."); emitRO("HALT",0,0,0,""); }
/* * Emit ASC code for a then statment as part of IF-THEN. * Assumes the corresposding statement or matched_stat code has already * been emitted. */ void emitThenStat() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); emitComment("Bottom of IF-THEN as part of IF-THEN"); emitLabel(STMT_LEN, "%s%d", LABEL_PREFIX, peekLabelStackTop(labelStack)); popLabels(labelStack); }
/* * Emit ASC code for an else statement * Assumes the corresponding statement code is already generated. */ void emitElseStat() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); emitComment("Bottom of ELSE stat"); emitLabel(STMT_LEN, "%s%d", LABEL_PREFIX, peekLabelStackTop(labelStack) + 1); popLabels(labelStack); }
/* * Emit code to goto the endo of the loop. Used for exit statments. */ void emitGotoLoopEnd() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); emitComment("Go to end of %s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack)); emitStmt(STMT_LEN, "GOTO %s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack) + 1); }
void emitHead() { emitComment(fileName); sprintf(buffer, ".class public %s", className); emitLine(buffer); emitLine(".super java/lang/Object"); emitLineBreak(); return; }
/* * Emit code for the end of a while loop. */ void emitEndWhile() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); emitComment("End of WHILE loop %s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack)); emitLabel(STMT_LEN, "%s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack) + 1); popLabels(loopLabelStack); }
/* * Check that expr is true to do loop, otherwise skip loop */ void emitWhileLoopCondCheck(Symbol *s) { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(s); if (! (s->kind == CONST_KIND && isConstResultSym(s))) { emitPushSymbolValue(s); } emitComment("If expr is false, skip loop body"); emitStmt(STMT_LEN, "IFZ %s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack) + 1); }
/* * Beginning of a while loop */ void emitBeginWhile() { /* we don't have a symbol pointer, so just pass in non-null */ CHECK_CAN_EMIT(1); /* Reserve loop labels. One for the top, one for the bottom */ reserveLabels(loopLabelStack, 2); emitComment("Top of WHILE loop %s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack)); emitLabel(STMT_LEN, "%s%d", LOOP_PREFIX, peekLabelStackTop(loopLabelStack)); }
/* * Emit the pre-defined ASC functions. */ void emitPreDefCode() { emitBlankLine(); emitSepLine(); emitBlankLine(); emitComment("Pre-defined ASC functions to follow"); emitBlankLine(); emitSepLine(); emitBlankLine(); /* call to generated function in PreDefAsc.c */ emitPreDefAsc(); }
/* * Emit ASC code to start an if statement. * Assumes the correspoding expression has already been emitted * * Note that both IF-THEN-ELSE and IF-THEN statements * reserve two labels, but only one is ever used in IF-THEN statements. */ void emitIfStat(Symbol *s) { CHECK_CAN_EMIT(s); /* reserve labels for THEN and ELSE */ reserveLabels(labelStack, 2); if (! (s->kind == CONST_KIND && isConstResultSym(s))) { emitPushSymbolValue(s); } emitComment("IF expr THEN. If 'expr' is false skip to %s%d", LABEL_PREFIX, peekLabelStackTop(labelStack)); emitStmt(STMT_LEN, "IFZ %s%d", LABEL_PREFIX, peekLabelStackTop(labelStack)); }
/* Procedure genExp generates code at an expression node */ static void genExp( TreeNode * tree) { int loc; TreeNode * p1, * p2; switch (tree->kind.exp) { case ConstK : if (TraceCode) emitComment("-> Const") ; /* gen code to load integer constant using LDC */ emitRM("LDC",ac,tree->attr.val,0,"load const"); if (TraceCode) emitComment("<- Const") ; break; /* ConstK */ case IdK : if (TraceCode) emitComment("-> Id") ; loc = st_lookup(tree->attr.name); emitRM("LD",ac,loc,gp,"load id value"); if (TraceCode) emitComment("<- Id") ; break; /* IdK */ case OpK : if (TraceCode) emitComment("-> Op") ; p1 = tree->child[0]; p2 = tree->child[1]; /* gen code for ac = left arg */ cGen(p1); /* gen code to push left operand */ emitRM("ST",ac,tmpOffset--,mp,"op: push left"); /* gen code for ac = right operand */ cGen(p2); /* now load left operand */ emitRM("LD",ac1,++tmpOffset,mp,"op: load left"); switch (tree->attr.op) { case PLUS : emitRO("ADD",ac,ac1,ac,"op +"); break; case MINUS : emitRO("SUB",ac,ac1,ac,"op -"); break; case TIMES : emitRO("MUL",ac,ac1,ac,"op *"); break; case OVER : emitRO("DIV",ac,ac1,ac,"op /"); break; case LT : emitRO("SUB",ac,ac1,ac,"op <") ; emitRM("JLT",ac,2,pc,"br if true") ; emitRM("LDC",ac,0,ac,"false case") ; emitRM("LDA",pc,1,pc,"unconditional jmp") ; emitRM("LDC",ac,1,ac,"true case") ; break; case EQ : emitRO("SUB",ac,ac1,ac,"op ==") ; emitRM("JEQ",ac,2,pc,"br if true"); emitRM("LDC",ac,0,ac,"false case") ; emitRM("LDA",pc,1,pc,"unconditional jmp") ; emitRM("LDC",ac,1,ac,"true case") ; break; default: emitComment("BUG: Unknown operator"); break; } /* case op */ if (TraceCode) emitComment("<- Op") ; break; /* OpK */ default: break; } } /* genExp */
/* Procedure genStmt generates code at a statement node */ static void genStmt( TreeNode * tree) { TreeNode * p1, * p2, * p3; int savedLoc1,savedLoc2,currentLoc; int loc; switch (tree->kind.stmt) { case IfK : if (TraceCode) emitComment("-> if") ; p1 = tree->child[0] ; p2 = tree->child[1] ; p3 = tree->child[2] ; /* generate code for test expression */ cGen(p1); savedLoc1 = emitSkip(1) ; emitComment("if: jump to else belongs here"); /* recurse on then part */ cGen(p2); savedLoc2 = emitSkip(1) ; emitComment("if: jump to end belongs here"); currentLoc = emitSkip(0) ; emitBackup(savedLoc1) ; emitRM_Abs("JEQ",ac,currentLoc,"if: jmp to else"); emitRestore() ; /* recurse on else part */ cGen(p3); currentLoc = emitSkip(0) ; emitBackup(savedLoc2) ; emitRM_Abs("LDA",pc,currentLoc,"jmp to end") ; emitRestore() ; if (TraceCode) emitComment("<- if") ; break; /* if_k */ case RepeatK: if (TraceCode) emitComment("-> repeat") ; p1 = tree->child[0] ; p2 = tree->child[1] ; savedLoc1 = emitSkip(0); emitComment("repeat: jump after body comes back here"); /* generate code for body */ cGen(p1); /* generate code for test */ cGen(p2); emitRM_Abs("JEQ",ac,savedLoc1,"repeat: jmp back to body"); if (TraceCode) emitComment("<- repeat") ; break; /* repeat */ case AssignK: if (TraceCode) emitComment("-> assign") ; /* generate code for rhs */ cGen(tree->child[0]); /* now store value */ loc = st_lookup(tree->attr.name); emitRM("ST",ac,loc,gp,"assign: store value"); if (TraceCode) emitComment("<- assign") ; break; /* assign_k */ case ReadK: emitRO("IN",ac,0,0,"read integer value"); loc = st_lookup(tree->attr.name); emitRM("ST",ac,loc,gp,"read: store value"); break; case WriteK: /* generate code for expression to write */ cGen(tree->child[0]); /* now output it */ emitRO("OUT",ac,0,0,"write ac"); break; default: break; } } /* genStmt */
/* Procedure emitBackup backs up to * loc = a previously skipped location */ void emitBackup( int loc) { if (loc > highEmitLoc) emitComment("BUG in emitBackup"); emitLoc = loc ; } /* emitBackup */
void montador(FILE *out, tipoInstr tipo, int valor, int reg){ static int memOffset = 0; switch(tipo){ case INSTR_INICIO: emitComment(out, "INICIO" ); emitRM(out, "LD",mp,0,ac,"load maxaddress from location 0"); emitRM(out, "ST",ac,0,ac,"clear location 0"); break; case INSTR_FIM: emitComment(out, "FIM" ); emitRO(out, "HALT",0,0,0,""); break; case INSTR_STORE_MEMORIA: emitComment(out, "STORE" ); emitRM(out, "ST",reg,valor,gp,"carrega endereco de memoria valor de gp em reg"); break; case INSTR_STORE_MEMORIA_TEMP: emitComment(out, "STORE TEMPORARIO" ); emitRM(out, "ST",reg,memOffset,mp,"carrega endereco de memoria valor de mp em reg"); memOffset--; break; case INSTR_LOAD_MEMORIA: emitComment(out, "LOAD" ); emitRM(out, "LD",reg,valor,gp,"carrega para reg o que tem no endereco de memoria valor que esta no gp"); break; case INSTR_LOAD_CTE: emitComment(out, "LOAD CONSTANTE" ); emitRM(out, "LDC",reg,valor,0,"carrega NUM em reg"); break; case INSTR_LOAD_MEMORIA_TEMP: emitComment(out, "LOAD O QUE ESTA NO TOPO DA PILHA DOS TEMPORARIOS" ); memOffset++; emitRM(out, "LD",reg,memOffset,mp,"carrega para reg o que tem no endereco de memoria valor que esta no mp"); break; case INSTR_WRITE: emitComment(out, "WRITE"); emitRO(out, "OUT",ac,0,0,"write ac"); break; case INSTR_TEMP_ACS: emitComment(out, "PASSA VALOR PARA AC0 E AC1"); memOffset++; emitRM(out, "LD",ac,memOffset,mp,"carrega em ac o que tem no endereco de memoria valor de mp"); memOffset++; emitRM(out, "LD",ac1,memOffset,mp,"carrega em ac1 o que tem no endereco de memoria valor de mp"); break; case INSTR_READ: emitComment(out, "READ"); emitRO(out, "IN", reg, 0, 0, "le valor para o registrador"); emitRM(out, "ST", reg, valor, gp, "armazena valor de reg para endereco de memoria valor de gp"); break; case INSTR_ADD: emitComment(out, "ADICAO"); emitRO(out, "ADD",ac,ac1,ac,"ac = ac1 + ac"); emitRM(out, "ST",ac,memOffset,mp,"armazena valor da soma na memoria mp"); memOffset--; break; case INSTR_SUB: emitComment(out, "SUBTRACAO"); emitRO(out, "SUB",ac,ac1,ac,"ac = ac1 - ac"); emitRM(out, "ST",ac,memOffset,mp,"armazena valor da subtracao na memoria mp"); memOffset--; break; case INSTR_MULT: emitComment(out, "MULTIPLICACAO"); emitRO(out, "MUL",ac,ac1,ac,"ac = ac1 * ac"); emitRM(out, "ST",ac,memOffset,mp,"armazena valor da multiplicacao na memoria mp"); memOffset--; break; case INSTR_DIV: emitComment(out, "DIVISAO"); emitRO(out, "DIV",ac,ac1,ac,"ac = ac1 / ac"); emitRM(out, "ST",ac,memOffset,mp,"armazena valor da divisao na memoria mp"); memOffset--; break; case INSTR_REL_MENOR: emitComment(out, "RELACAO: MENOR"); emitRO(out, "SUB",ac,ac1,ac,""); emitRM(out, "JLT",ac,4,pc,"a - b < 0 ? Se sim, pule para armazenar true"); break; case INSTR_REL_MENOR_IGUAL: emitComment(out, "RELACAO: MENOR IGUAL"); emitRO(out, "SUB",ac,ac1,ac,"op - entre ac e ac1"); emitRM(out, "JLE",ac,4,pc,"a - b <= 0 ? Se sim, pule para armazenar true"); break; case INSTR_REL_MAIOR: emitComment(out, "RELACAO: MAIOR"); emitRO(out, "SUB",ac,ac1,ac,""); emitRM(out, "JGT",ac,4,pc,"a - b > 0 ? Se sim, pule para armazenar true"); break; case INSTR_REL_MAIOR_IGUAL: emitComment(out, "RELACAO: MAIOR IGUAL"); emitRO(out, "SUB", ac, ac1, ac, "op - entre ac e ac1"); emitRM(out, "JGE", ac, 4, pc, "a-b>=0 ? Se sim, pula para armazenar true"); break; case INSTR_REL_IGUAL: emitComment(out, "RELACAO: IGUAL"); emitRO(out, "SUB",ac,ac1,ac,""); emitRM(out, "JEQ",ac,4,pc,"a - b == 0 ? Se sim, pule para armazenar true"); break; case INSTR_REL_DIF: emitComment(out, "RELACAO: DIFERENTE"); emitRO(out, "SUB",ac,ac1,ac,"op - entre ac e ac1"); emitRM(out, "JNE",ac,4,pc,"a - b != 0 ? Se sim, pule para armazenar true"); break; case INSTR_REL_AND: emitComment(out, "OPERACAO LOGICA: AND"); emitRM(out, "JEQ", ac, 3, pc, "ac == 0? Se sim, avalia como falso"); emitRM(out, "JEQ", ac1, 2, pc, "ac1 == 0? Se sim, avalia como falso"); emitRM(out, "LDC",ac,0,0,""); emitRM(out, "JEQ",ac,4,pc,"Se nenhum dos dois é falso, avalia como verdadeiro"); break; case INSTR_REL_OR: emitComment(out, "OPERACAO LOGICA: OR"); emitRM(out, "JNE", ac, 5, pc, "ac != 0? Se sim, avalia como true"); emitRM(out, "JNE", ac1, 4, pc, "ac1 != 0? Se sim, avalia como true"); emitComment(out, "se nenhum dos dois e verdadeiro, avalia como falso, nao pula"); break; case INSTR_STORE_REL: emitComment(out, "STORE RESULTADO DA RELACAO"); emitRM(out, "LDC",ac,0,0,"false"); emitRM(out, "ST",ac,memOffset,mp,"armazena false no topo"); emitRM(out, "LDC",ac,0,0,""); emitRM(out, "JEQ",ac,2,pc,"Pula para o if"); emitRM(out, "LDC",ac,1,0,"true"); emitRM(out, "ST",ac,memOffset,mp,"armazena true no topo"); memOffset--; break; case INSTR_JUMP_REL_FALSE: emitComment(out, "JUMP se o valor da relacao for false"); memOffset++; emitRM(out, "LD",ac,memOffset,mp,""); emitRM(out, "JEQ",ac,valor,pc,"Pula para o else"); break; case INSTR_JUMP: emitComment(out, "JUMP"); emitRM(out, "LDC",ac,0,0,""); emitRM(out, "JEQ",ac,valor,pc,"Pula incondicionalmente para pc+valor"); break; default: emitComment(out, "ERRO" ); break; } }
void escreverComentario(FILE *out, char *str){ emitComment(out, str ); }
/* * Emit anything that must be emitted before the code generated from the * input PAL. This includes predefined funcs and procs, constants, etc. */ void emitInit() { emitComment("ASC code generated by Yet Another CMPUT415 Compiler."); emitComment("May the Force be ever in your favour, Mr. Potter."); emitComment("CMPUT 415 - Fall 2013"); emitBlankLine(); }
void codeGen(TreeNode* currnode) { bool texp = false; while(currnode != NULL) { if(currnode->nodekind==DeclK) { switch(currnode->kind.decl) { case varK: codeGen(currnode->child[0]); t2 = (TreeNode*)tab->lookup(currnode->attr.name); if(t2 == NULL && currnode->isArray) { emitRM2((char*)"LDC", AC, currnode->size - 1, AC3, (char*)"load size of array", currnode->attr.name); emitRM2((char*)"ST", AC, currnode->location + 1, FP, (char*)"save size of array", currnode->attr.name); } if(t2 == NULL && currnode->child[0] != NULL) emitRM2((char*)"ST", AC, currnode->location, FP, (char*)"Store variable", currnode->attr.name); if(t2 != NULL && currnode->child[0] != NULL) codeGen(currnode->child[0]); break; case paramK: break; case funcK: //printf("test\n"); t1 = (TreeNode*)tab->lookup(currnode->attr.name); t1->location = emitSkip(0); currnode->location = t1->location; toff = 0; framesize = currnode->size; //toff = 0 - t1->size; emitComment2((char*)"BEGIN function", currnode->attr.name); if(currnode->isPre) emitRM((char*)"ST", AC, -1, FP, (char*)"Store return address"); else emitRM((char*)"ST", AC, -1, FP, (char*)"Store return address."); codeGen(currnode->child[0]); codeGen(currnode->child[1]); if(currnode->isPre) { switch(currnode->pnum) { case 0://input emitRO((char*)"IN", RT, RT, RT, (char*)"Grab int input"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 1://output emitRM((char*)"LD", AC, -2, FP, (char*)"Load parameter"); emitRO((char*)"OUT", AC, AC, AC, (char*)"Output integer"); emitRM((char*)"LDC", RT, 0, AC3, (char*)"Set return to 0"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 2://inputb emitRO((char*)"INB", RT, RT, RT, (char*)"Grab bool input"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 3://ouptutb emitRM((char*)"LD", AC, -2, FP, (char*)"Load parameter"); emitRO((char*)"OUTB", AC, AC, AC, (char*)"Output bool"); emitRM((char*)"LDC", RT, 0, AC3, (char*)"Set return to 0"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 4://inputc emitRO((char*)"INC", RT, RT, RT, (char*)"Grab char input"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 5://outputc emitRM((char*)"LD", AC, -2, FP, (char*)"Load parameter"); emitRO((char*)"OUTC", AC, AC, AC, (char*)"Output char"); emitRM((char*)"LDC", RT, 0, AC3, (char*)"Set return to 0"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case 6://outnl emitRO((char*)"OUTNL", AC, AC, AC, (char*)"Output a newline"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); } } if(!currnode->isPre) { emitComment((char*)"Add standard closing in case there is no return statement"); emitRM((char*)"LDC", RT, 0, AC3, (char*)"Set return value to 0"); emitRM((char*)"LD", AC, -1, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, 0, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); } emitComment2((char*)"END of function", currnode->attr.name); toff = 0; break; } //in_exp = false; } else if(currnode->nodekind==StmtK) switch(currnode->kind.stmt) { case ifK: int breakk; int breakk2; emitComment((char*)"IF"); currloc2 = emitSkip(0); ifexp = true; codeGen(currnode->child[0]); ifexp = false; emitRM((char*)"JGT", AC, 1, PC, (char*)"Jump to then part"); emitComment((char*)"THEN"); skiploc2 = breakk2; breakk2 = emitSkip(1); codeGen(currnode->child[1]); if(currnode->child[2] != NULL) { emitComment((char*)"ELSE"); breakk = emitSkip(1); backPatchJumpToHere(breakk2, (char*)"Jump around the THEN [backpatch]"); codeGen(currnode->child[2]); backPatchJumpToHere(breakk, (char*)"Jump around the ELSE [backpatch]"); } else backPatchJumpToHere(breakloc, (char*)"Jump around the THEN [backpatch]"); emitComment((char*)"ENDIF"); break; case returnK: emitComment((char*)"RETURN"); if (currnode->child[0] != NULL) { codeGen(currnode->child[0]); // generate any return value //t2 = (TreeNode*)tab->lookup(currnode->attr.name); if(currnode->child[0] != NULL) { if(currnode->child[0]->scopeT == local || currnode->child[0]->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[0]->isArray) { if(currnode->scopeT == param) emitRM2((char*)"LD", AC1, currnode->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC, currnode->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRM2((char*)"SUB", AC, AC1, AC, (char*)"Compute offset for", currnode->attr.name); emitRM2((char*)"LD", AC, 0, AC, (char*)"load the value", currnode->attr.name); } emitRM((char*)"LDA", RT, 0, AC, (char*)"Copy result to rt register"); // save in return register } // emit return sequence emitRM((char*)"LD", AC, OFPOFF, FP, (char*)"Load return address"); emitRM((char*)"LD", FP, RETURN_OFFSET, FP, (char*)"Adjust fp"); emitRM((char*)"LDA", PC, 0, AC, (char*)"Return"); break; case compoundK: emitComment((char*)"BEGIN compound statement"); codeGen(currnode->child[0]); codeGen(currnode->child[1]); emitComment((char*)"END compound statement"); break; case breakK: emitComment((char*)"BREAK"); emitRM((char*)"LDA", PC, breakloc - emitSkip(0) - 1, PC, (char*)"break"); break; case foreachK: break; case whileK: int currloc; int skiploc; emitComment((char*)"WHILE"); currloc = emitSkip(0); // save location to return to codeGen(currnode->child[0]); // generate code for test emitRM((char*)"JGT", AC, 1, PC, (char*)"Jump to while part"); // test and jump emitComment((char*)"DO"); skiploc = breakloc; // save the old break statement return point breakloc = emitSkip(1); // addr of instr that jumps to end of loop // this is also the backpatch point codeGen(currnode->child[1]); // generate body of loop emitRMAbs((char*)"LDA", PC, currloc, (char*)"go to beginning of loop"); // jump to top of loop backPatchJumpToHere(breakloc, (char*)"No more loop [backpatch]"); // backpatch jump to end of loop at breakloc breakloc = skiploc; // restore for break statement emitComment((char*)"ENDWHILE"); break; } else if(currnode->nodekind==ExpK) { int offReg = 1; if(!in_exp) { emitComment((char*)"EXPRESSION STMT"); in_exp = true; } switch(currnode->kind.exp) { codeGen(currnode->child[0]); case opK: texp = inexp; inexp = currnode->expType == Bool; opexp = true; //tempparam = params; //params = 1; codeGen(currnode->child[0]); opexp = false; //params = tempparam; if(currnode->child[1] != NULL) { emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save left side"); if(!currnode->child[1]->isArray) codeGen(currnode->child[1]); else { codeGen(currnode->child[1]->child[0]); t2 = (TreeNode*)tab->lookup(currnode->child[1]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[1]->scopeT == param) { if(currnode->child[1]->child[0] != NULL) emitRM2((char*)"LD", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[1]->attr.name); else emitRM2((char*)"LD", AC, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[1]->attr.name); } else { if(currnode->child[0] != NULL) { emitRO((char*)"SUB", AC, AC1, AC, (char*)"Computer offset of value"); emitRM((char*)"LD", AC, 0, AC, (char*)"Load the value"); } } } emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Load left into ac1"); } switch(currnode->attr.op) { case ltK: emitRO((char*)"SUB", AC1, AC1, AC, (char*)"Op <"); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); emitRM((char*)"JLT", AC1, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 0, AC3, (char*)"False case"); break; case gtK: emitRO((char*)"SUB", AC1, AC1, AC, (char*)"Op <"); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); emitRM((char*)"JGT", AC1, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 0, AC3, (char*)"False case"); break; case equivK: emitRO((char*)"SUB", AC1, AC1, AC, (char*)"Op =="); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); emitRM((char*)"JEQ", AC1, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 0, AC3, (char*)"False case"); break; case neqK: emitRO((char*)"SUB", AC, AC1, AC, (char*)"Op !="); emitRM((char*)"JEQ", AC, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); break; case modK: emitRO((char*)"DIV", AC2, AC1, AC, (char*)"Op %"); emitRO((char*)"MUL", AC2, AC2, AC, (char*)""); emitRO((char*)"SUB", AC, AC1, AC2, (char*)""); break; case UminusK: emitRM((char*)"LDC", AC1, 0, AC3, (char*)"Load 0"); emitRO((char*)"SUB", AC, AC1, AC, (char*)"Op unary -"); break; case UmultiK: emitRO((char*)"MUL", AC, currnode->size + 1, AC, (char*)"Load array size"); break; case minusK: emitRO((char*)"SUB", AC, AC1, AC, (char*)"Op -"); break; case plusK: emitRO((char*)"ADD", AC, AC1, AC, (char*)"Op +"); break; case multiK: emitRO((char*)"MUL", AC, AC1, AC, (char*)"Op *"); break; case divideK: emitRO((char*)"DIV", AC, AC1, AC, (char*)"Op /"); break; case lteqK: emitRO((char*)"SUB", AC1, AC1, AC, (char*)"Op <="); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); emitRM((char*)"JLE", AC1, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 0, AC3, (char*)"False case"); break; case gteqK: emitRO((char*)"SUB", AC1, AC1, AC, (char*)"Op >="); emitRM((char*)"LDC", AC, 1, AC3, (char*)"True case"); emitRM((char*)"JGE", AC1, 1, PC, (char*)"Jump if true"); emitRM((char*)"LDC", AC, 0, AC3, (char*)"False case"); break; case notK: emitRM((char*)"LDA", AC, 1, AC2, (char*)"Not load address"); emitRO((char*)"SUB", AC, AC1, AC, (char*)"Op Not"); break; case andK: emitRM((char*)"JEQ", AC, 1, PC, (char*)"Op AND"); emitRM((char*)"LDA", AC, 0, AC2, (char*)""); break; case orK: emitRM((char*)"JEQ", AC, 1, PC, (char*)"Op OR"); emitRM((char*)"LDA", AC, 0, AC2, (char*)""); break; } inexp = texp; break; case constK: if(currnode->expType == Int) emitRM((char*)"LDC", AC, currnode->attr.val, AC3, (char*)"Load constant"); if(currnode->expType == Bool) { if(currnode->attr.bval) emitRM((char*)"LDC", AC, 1, AC3, (char*)"Load constant"); else emitRM((char*)"LDC", AC, 0, AC3, (char*)"Load constant"); } if(currnode->expType == Char) emitRM((char*)"LDC",AC, currnode->attr.string[1], AC3, (char*)"Load constant"); break; case idK: codeGen(currnode->child[0]); t2 = (TreeNode*)tab->lookup(currnode->attr.name); if(t2 != NULL) { if(currnode->scopeT == local || currnode->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->isArray) { if((params != 0 && !inexp) || opexp || ifexp) { if(currnode->scopeT == param) { //emitRM2((char*)"LD", AC1, currnode->location, FP, (char*)"Load address of base of array", currnode->attr.name); if(currnode->child[0] != NULL) emitRM2((char*)"LD", AC1, currnode->location, offReg, (char*)"Load address of base of array", currnode->attr.name); else emitRM2((char*)"LD", AC, currnode->location, offReg, (char*)"Load address of base of array", currnode->attr.name); } else { if(currnode->child[0] != NULL) emitRM2((char*)"LDA", AC1, currnode->location, offReg, (char*)"Load address of base of array", currnode->attr.name); else emitRM2((char*)"LDA", AC, currnode->location, offReg, (char*)"Load address of base of array", currnode->attr.name); } if(currnode->child[0] != NULL) { emitRO((char*)"SUB", AC, AC1, AC, (char*)"Compute offset of value"); emitRM((char*)"LD", AC, 0, AC, (char*)"load the value"); } } //in = true; } else if(currnode->scopeT != param && currnode->scopeT != local) emitRM2((char*)"LD", AC, currnode->location, offReg, (char*)"Load variable", currnode->attr.name); else emitRM2((char*)"LD", AC, currnode->location, offReg, (char*)"Load variable", currnode->attr.name); break; case assignK: texp = inexp; inexp = true; switch(currnode->attr.op) { case peqK: if(currnode->child[0]->isArray) { codeGen(currnode->child[0]); emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save index"); } codeGen(currnode->child[1]); t2 = (TreeNode*)tab->lookup(currnode->child[0]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[1]->isArray) { if(currnode->child[1]->scopeT == param) emitRM2((char*)"LD", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC, AC1, AC, (char*)"Compute offset of value"); emitRM((char*)"LD", AC, 0, AC2, (char*)"Load the value"); } if(currnode->child[0]->isArray) { emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Restore index"); if(currnode->child[0]->scopeT == param) emitRM2((char*)"LD", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC2, AC2, AC1, (char*)"Compute offset of value"); emitRM2((char*)"LD", AC1, 0, AC2, (char*)"loah lhs variable", currnode->child[0]->attr.name); emitRO((char*)"ADD", AC, AC1, AC, (char*)"op +="); // decrement emitRM2((char*)"ST", AC, 0, AC2, (char*)"Store variable", currnode->child[0]->attr.name); } else { emitRM2((char*)"LD", AC1, currnode->child[0]->location, offReg, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRO((char*)"ADD", AC, AC1, AC, (char*)"op +="); // decrement emitRM2((char*)"ST", AC, currnode->child[0]->location, offReg, (char*)"Store variable", currnode->child[0]->attr.name); // store mutable } break; case meqK: if(currnode->child[0]->isArray) { codeGen(currnode->child[0]); emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save index"); } codeGen(currnode->child[1]); t2 = (TreeNode*)tab->lookup(currnode->child[0]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[1]->isArray) { if(currnode->child[1]->scopeT == param) emitRM2((char*)"LD", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC, AC1, AC, (char*)"Compute offset of value"); emitRM((char*)"LD", AC, 0, AC2, (char*)"Load the value"); } if(currnode->child[0]->isArray) { emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Restore index"); if(currnode->child[0]->scopeT == param) emitRM2((char*)"LD", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC2, AC2, AC1, (char*)"Compute offset of value"); emitRM2((char*)"LD", AC1, 0, AC2, (char*)"loah lhs variable", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC, AC1, AC, (char*)"op -="); // decrement emitRM2((char*)"ST", AC, 0, AC2, (char*)"Store variable", currnode->child[0]->attr.name); } else { emitRM2((char*)"LD", AC1, currnode->child[0]->location, offReg, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRO((char*)"SUB", AC, AC1, AC, (char*)"op -="); // decrement emitRM2((char*)"ST", AC, currnode->child[0]->location, offReg, (char*)"Store variable", currnode->child[0]->attr.name); // store mutable } break; case eqK: if(currnode->child[0]->isArray) { codeGen(currnode->child[0]); emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save index"); } codeGen(currnode->child[1]); t2 = (TreeNode*)tab->lookup(currnode->child[0]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[1]->isArray) { if(currnode->child[1]->scopeT == param) emitRM2((char*)"LD", AC1, currnode->child[1]->location, offReg, (char*)"Load address of base of array", currnode->child[1]->attr.name); else emitRM2((char*)"LDA", AC1, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC, AC1, AC, (char*)"Compute offset of value"); emitRM((char*)"LD", AC, 0, AC, (char*)"Load the value"); } if(currnode->child[0]->isArray) { emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Restore index"); if(currnode->child[0]->scopeT == param) emitRM2((char*)"LD", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC2, AC2, AC1, (char*)"Compute offset of value"); emitRM2((char*)"ST", AC, 0, AC2, (char*)"Store variable", currnode->child[0]->attr.name); } else emitRM2((char*)"ST", AC, currnode->child[0]->location, offReg, (char*)"Store variable", currnode->child[0]->attr.name); break; case ppK: if(currnode->child[0]->isArray) { codeGen(currnode->child[0]); emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save index"); } //codeGen(currnode->child[0]); t2 = (TreeNode*)tab->lookup(currnode->child[0]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[0]->isArray) { emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Restore index"); if(currnode->child[0]->scopeT == param) emitRM2((char*)"LD", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC2, AC2, AC1, (char*)"Compute offset of the value"); emitRM2((char*)"LD", AC, 0, AC2, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRM2((char*)"LDA", AC, 1, AC, (char*)"increment value of", currnode->child[0]->attr.name); // decrement emitRM2((char*)"ST", AC, 0, AC2, (char*)"Store variable", currnode->child[0]->attr.name); } else { emitRM2((char*)"LD", AC, currnode->child[0]->location, offReg, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRM2((char*)"LDA", AC, 1, AC, (char*)"increment value of", currnode->child[0]->attr.name); // decrement emitRM2((char*)"ST", AC, currnode->child[0]->location, offReg, (char*)"Store variable", currnode->child[0]->attr.name); // store mutable } break; case mmK: if(currnode->child[0]->isArray) { codeGen(currnode->child[0]); emitRM((char*)"ST", AC, toff-- - framesize, FP, (char*)"Save index"); } //codeGen(currnode->child[0]); t2 = (TreeNode*)tab->lookup(currnode->child[0]->attr.name); if(t2 != NULL) { if(t2->scopeT == local || t2->scopeT == param) offReg = 1; else offReg = 0; } if(currnode->child[0]->isArray) { emitRM((char*)"LD", AC1, ++toff - framesize, FP, (char*)"Restore index"); if(currnode->child[0]->scopeT == param) emitRM2((char*)"LD", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); else emitRM2((char*)"LDA", AC2, currnode->child[0]->location, offReg, (char*)"Load address of base of array", currnode->child[0]->attr.name); emitRO((char*)"SUB", AC2, AC2, AC1, (char*)"Compute offset of the value"); emitRM2((char*)"LD", AC, 0, AC2, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRM2((char*)"LDA", AC, -1, AC, (char*)"increment value of", currnode->child[0]->attr.name); // decrement emitRM2((char*)"ST", AC, 0, AC2, (char*)"Store variable", currnode->child[0]->attr.name); } else { emitRM2((char*)"LD", AC, currnode->child[0]->location, offReg, (char*)"load lhs variable", currnode->child[0]->attr.name); // load mutable emitRM2((char*)"LDA", AC, -1, AC, (char*)"increment value of", currnode->child[0]->attr.name); // decrement emitRM2((char*)"ST", AC, currnode->child[0]->location, offReg, (char*)"Store variable", currnode->child[0]->attr.name); // store mutable } break; inexp = texp; } inexp = false; break; case callK: texp = inexp; inexp = false; int ttemp = toff; TreeNode *tmp = currnode->child[0]; //emitComment((char*)"EXPRESSION STMT"); emitComment2((char*)"\t\t\tBegin call to ", currnode->attr.name); emitRM((char*)"ST", FP, toff - framesize, 1, (char*)"Store old fp in ghost frame"); toff -= 2; while(tmp != NULL) { params++; emitComment((char*)"\t\t\tLoad param 1"); codeGen(tmp); emitRM((char*)"ST", AC, toff-- - framesize,FP, (char*)"Store parameter"); paramoff--; tmp = tmp->sibling; params--; } toff = ttemp; paramoff = -2; //t1 = (TreeNode*)tab->lookup(currnode->attr.name); emitComment2((char*)"\t\t\tJump to", currnode->attr.name); emitRM((char*)"LDA", FP, toff - framesize, 1, (char*)"Load address of new frame"); emitRM((char*)"LDA", AC, 1, PC, (char*)"Return address in ac"); //FIX THE DAMN symbtable TreeNode* t = (TreeNode*)tab->lookup(currnode->attr.name); emitRM2((char*)"LDA", PC, t->location - emitSkip(0) - 1, PC, (char*)"CALL", t->attr.name); emitRM((char*)"LDA", AC, 0, RT, (char*)"Save the result in ac"); emitComment2((char*)"\t\t\tEnd call to", currnode->attr.name); emitComment((char*)"EXPRESSION STMT"); calloff += 2; inexp = texp; break; }//end switch exp in_exp = false; }//end expK //else printf("Unknown node kind"); if(params == 0) currnode = currnode->sibling; else currnode = NULL; }//end while }//end function
void emitHeaderStart() { const char *tn = ls.structname.fullname.c_str(); const char *sn = ls.structname.shortname.c_str(); string tnDots = dotsToUnderscores(ls.structname.fullname); const char *tn_ = tnDots.c_str(); emitAutoGeneratedWarning(); emit(0, "#include <zcm/zcm_coretypes.h>"); emit(0, ""); emit(0, "#ifndef __%s_hpp__", tn_); emit(0, "#define __%s_hpp__", tn_); emit(0, ""); // do we need to #include <vector> and/or <string>? bool emitIncludeVector = false; bool emitIncludeString = false; for (auto& lm : ls.members) { if (!emitIncludeVector && lm.dimensions.size() != 0 && !lm.isConstantSizeArray()) { emit(0, "#include <vector>"); emitIncludeVector = true; } if (!emitIncludeString && lm.type.fullname == "string") { emit(0, "#include <string>"); emitIncludeString = true; } } // include header files for other ZCM types for (auto& lm : ls.members) { auto& mtn = lm.type.fullname; if (!ZCMGen::isPrimitiveType(mtn) && mtn != tn) { emit(0, "#include \"%s%s%s.hpp\"", zcm.gopt->getString("cpp-include").c_str(), zcm.gopt->getString("cpp-include").size()>0 ? "/":"", dotsToSlashes(mtn).c_str()); } } emit(0, "\n"); emitPackageNamespaceStart(); // define the class emitComment(0, ls.comment); emit(0, "class %s", sn); emit(0, "{"); // data members if(ls.members.size() > 0) { emit(1, "public:"); for (auto& lm : ls.members) { auto& mtn = lm.type.fullname; emitComment(2, lm.comment); string mappedTypename = mapTypeName(mtn); int ndim = (int)lm.dimensions.size(); if (ndim == 0) { emit(2, "%-10s %s;", mappedTypename.c_str(), lm.membername.c_str()); } else { if (lm.isConstantSizeArray()) { emitStart(2, "%-10s %s", mappedTypename.c_str(), lm.membername.c_str()); for (auto& ld : lm.dimensions) emitContinue("[%s]", ld.size.c_str()); emitEnd(";"); } else { emitStart(2, ""); for (int d = 0; d < ndim; d++) emitContinue("std::vector< "); emitContinue("%s", mappedTypename.c_str()); for (int d = 0; d < ndim; d++) emitContinue(" >"); emitEnd(" %s;", lm.membername.c_str()); } } emit(0, ""); } } // constants if (ls.constants.size() > 0) { emit(1, "public:"); emit(2, "#if __cplusplus > 199711L /* if c++11 */"); for (auto& lc : ls.constants) { assert(ZCMGen::isLegalConstType(lc.type)); emitComment(2, lc.comment); string mt = mapTypeName(lc.type); const char *suffix = lc.type == "int64_t" ? "LL" : ""; emit(2, "static constexpr %-8s %s = %s%s;", mt.c_str(), lc.membername.c_str(), lc.valstr.c_str(), suffix); } emit(2, "#else"); for (auto& lc : ls.constants) { assert(ZCMGen::isLegalConstType(lc.type)); string mt = mapTypeName(lc.type); const char *suffix = lc.type == "int64_t" ? "LL" : ""; emit(2, "static const %-8s %s = %s%s;", mt.c_str(), lc.membername.c_str(), lc.valstr.c_str(), suffix); } emit(2, "#endif"); emit(0, ""); } emit(1, "public:"); emit(2, "/**"); emit(2, " * Destructs a message properly if anything inherits from it"); emit(2, "*/"); emit(2, "virtual ~%s() {}", ls.structname.shortname.c_str()); emit(0, ""); emit(2, "/**"); emit(2, " * Encode a message into binary form."); emit(2, " *"); emit(2, " * @param buf The output buffer."); emit(2, " * @param offset Encoding starts at thie byte offset into @p buf."); emit(2, " * @param maxlen Maximum number of bytes to write. This should generally be"); emit(2, " * equal to getEncodedSize()."); emit(2, " * @return The number of bytes encoded, or <0 on error."); emit(2, " */"); emit(2, "inline int encode(void *buf, int offset, int maxlen) const;"); emit(0, ""); emit(2, "/**"); emit(2, " * Check how many bytes are required to encode this message."); emit(2, " */"); emit(2, "inline int getEncodedSize() const;"); emit(0, ""); emit(2, "/**"); emit(2, " * Decode a message from binary form into this instance."); emit(2, " *"); emit(2, " * @param buf The buffer containing the encoded message."); emit(2, " * @param offset The byte offset into @p buf where the encoded message starts."); emit(2, " * @param maxlen The maximum number of bytes to reqad while decoding."); emit(2, " * @return The number of bytes decoded, or <0 if an error occured."); emit(2, " */"); emit(2, "inline int decode(const void *buf, int offset, int maxlen);"); emit(0, ""); emit(2, "/**"); emit(2, " * Retrieve the 64-bit fingerprint identifying the structure of the message."); emit(2, " * Note that the fingerprint is the same for all instances of the same"); emit(2, " * message type, and is a fingerprint on the message type definition, not on"); emit(2, " * the message contents."); emit(2, " */"); emit(2, "inline static int64_t getHash();"); emit(0, ""); emit(2, "/**"); emit(2, " * Returns \"%s\"", ls.structname.shortname.c_str()); emit(2, " */"); emit(2, "inline static const char* getTypeName();"); emit(0, ""); emit(2, "// ZCM support functions. Users should not call these"); emit(2, "inline int _encodeNoHash(void *buf, int offset, int maxlen) const;"); emit(2, "inline int _getEncodedSizeNoHash() const;"); emit(2, "inline int _decodeNoHash(const void *buf, int offset, int maxlen);"); emit(2, "inline static uint64_t _computeHash(const __zcm_hash_ptr *p);"); emit(0, "};"); emit(0, ""); }
// emitBackup backs up to // loc = a previously skipped location // void emitBackup(int loc) { if (loc>highEmitLoc) emitComment((char *)"BUG in emitBackup"); emitLoc = loc; }