void term() { // assert: n = allocatedRegisters // remember operator symbol // must be local variable to work for nested expressions int operatorSymbol; factor(); // assert: allocatedRegisters == n + 1 while (isSymbolAsteriskOrSlash()) { operatorSymbol = symbol; getSymbol(); term(); if (operatorSymbol == ASTERISK) emitCode(MUL, allocatedRegisters - 1, allocatedRegisters - 1, allocatedRegisters); else emitCode(DIV, allocatedRegisters - 1, allocatedRegisters - 1, allocatedRegisters); allocatedRegisters = allocatedRegisters - 1; } // assert: allocatedRegisters == n + 1 }
static void parse_finish_branch (git_uint32* pc, Label op, LoadReg reg, int mode) { git_sint32 val; if (parseLoad (pc, reg, mode, size32, &val)) { // The branch offset is a constant, so we can // check for the special values 0 and 1 right here. if (val == 0) { emitCode (op - label_jeq_var + label_jeq_return0); } else if (val == 1) { emitCode (op - label_jeq_var + label_jeq_return1); } else { // Calculate the destination address and // emit a constant branch opcode. emitConstBranch (op - label_jeq_var + label_jeq_const, *pc + val - 2); } } else { // The branch offset isn't a constant, so just // emit the normal opcode plus the current PC. emitCode (op); emitData(*pc); } }
void emitExit() { int* identifierCursor; // "exit" is 4 characters plus null termination identifier = malloc(5 * 4); identifierCursor = identifier; *identifierCursor = 101; // ASCII code 101 = e identifierCursor = identifierCursor + 1; *identifierCursor = 120; // ASCII code 120 = x identifierCursor = identifierCursor + 1; *identifierCursor = 105; // ASCII code 105 = i identifierCursor = identifierCursor + 1; *identifierCursor = 116; // ASCII code 116 = t identifierCursor = identifierCursor + 1; *identifierCursor = 0; // end of identifier // current code length is address of next instruction createSymbolTableEntry(codeLength); // retrieve error code from stack into register 1 emitCode(LDW, 1, SP, 0); // halt machine, return error code from register 1 emitCode(HLT, 0, 0, 1); }
//int main() { this causes a name collision when hosted on linux... int parser_main() { // pick some maximum identifier length, e.g. 42 characters maxIdentifierLength = 42; LINK = 31; SP = 30; FP = 29; GP = 28; RR = 27; // ... ZR = 0; allocatedRegisters = 0; allocatedGlobalVariables = 0; ADD = 7; // opcode for ADD SUB = 8; // opcode for SUB // ... symbolTable = 0; // pick some maximum code length, e.g. 16K * 4 bytes = 64KB // increase as needed maxCodeLength = 16384; // allocate memory for emitting code code = malloc(maxCodeLength * 4); codeLength = 0; // start executing by branching to main procedure // please do not forget: parameter c requires fixup // when code location for main procedure is known emitCode(BSR, 0, 0, 0); // push exit code in return register onto stack emitCode(PSH, RR, SP, 4); // halt machine by invoking exit emitCode(BSR, 0, 0, codeLength + 1); // emit library code for exit right here emitExit(); // similarly, emit library code for malloc, getchar, and putchar // ... // get first symbol from scanner getSymbol(); // invoke compiler, implement missing procedures cstar(); // write code to standard output writeBinary(); return 0; }
void factor() { int symbol; // assert: n = allocatedRegisters // have we parsed an asterisk sign? // must be local variable to work for nested expressions int dereference; cast(); if (symbol == ASTERISK) { dereference = 1; getSymbol(); } else dereference = 0; if (symbol == IDENTIFIER) { allocatedRegisters = allocatedRegisters + 1; emitCode(LDW, allocatedRegisters, GP, getGlobalVariableOffset()); getSymbol(); } else if (symbol == INTEGER) { allocatedRegisters = allocatedRegisters + 1; emitCode(ADDI, allocatedRegisters, ZR, integer); getSymbol(); } else if (symbol == LEFTPARENTHESIS) { getSymbol(); expression(); if (symbol == RIGHTPARENTHESIS) getSymbol(); else syntaxError(FACTOR); // right parenthesis expected! } else syntaxError(FACTOR); // identifier, integer, or left parenthesis expected! if (dereference) emitCode(LDW, allocatedRegisters, allocatedRegisters, 0); // assert: allocatedRegisters == n + 1 }
int expression() { int symbol; // assert: n = allocatedRegisters // have we parsed a minus sign? // must be local variable to work for nested expressions int sign; // remember operator symbol // must be local variable to work for nested expressions int operatorSymbol; if (symbol == MINUS) { sign = 1; getSymbol(); } else sign = 0; term(); // assert: allocatedRegisters == n + 1 if (sign) emitCode(SUB, allocatedRegisters, ZR, allocatedRegisters); while (isSymbolPlusOrMinus()) { operatorSymbol = symbol; getSymbol(); term(); if (operatorSymbol == PLUS) emitCode(ADD, allocatedRegisters - 1, allocatedRegisters - 1, allocatedRegisters); else emitCode(SUB, allocatedRegisters - 1, allocatedRegisters - 1, allocatedRegisters); allocatedRegisters = allocatedRegisters - 1; } // assert: allocatedRegisters == n + 1 // enhance to return BEQ, BNE, etc. // depending on parsed comparison operator return 0; }
static void emit_insn2(int64_t oc) { emitCode(oc & 255); emitCode((oc >> 8) & 255); emitCode((oc >> 16) & 255); emitCode((oc >> 24) & 255); emitCode((oc >> 32) & 255); }
static void parseL (git_uint32* pc, Label op) { int modes [1]; parseModeNibbles (pc, 1, modes); parseLoad (pc, reg_L1, modes [0], size32, NULL); emitCode (op); }
static void parseS (git_uint32* pc, Label op) { int modes [1]; parseModeNibbles (pc, 1, modes); emitCode (op); parseStore (pc, reg_S1, modes [0], size32); }
static void parseLS (git_uint32* pc, Label op) { int modes [2]; parseModeNibbles (pc, 2, modes); parseLoad (pc, reg_L1, modes [0], size32, NULL); emitCode (op); parseStore (pc, reg_S1, modes [1], size32); }
static void emitImm0(int64_t v, int force) { if (v != 0 || force) { emitAlignedCode(0xfd); emitCode(v & 255); emitCode((v >> 8) & 255); emitCode((v >> 16) & 255); emitCode((v >> 24) & 255); }
void test_emitCode_given_index_257_should_translate_to_nan_and_output_nan(){ Dictionary *dictionary = dictionaryNew(100); dictionary->entries[1].code = "nan"; OutStream out; int index = 257; streamWriteBits_Expect(&out, 110, 8); streamWriteBits_Expect(&out, 97, 8); streamWriteBits_Expect(&out, 110, 8); emitCode(dictionary, index, &out); }
void test_emitCode_given_index_neg_1_should_throw_error(){ CEXCEPTION_T e; Dictionary *dictionary = dictionaryNew(100); OutStream out; int index = -1; Try{ emitCode(dictionary, index, &out); }Catch(e){ TEST_ASSERT_EQUAL(ERR_INVALID_INDEX, e); } }
/* * DoEmitCode - build callback routine thunk */ static CALLBACKPTR DoEmitCode( int argcnt, int bytecnt, char *array, DWORD fn, int is_cdecl ) { int codesize; int i; /* * get a callback jump table entry */ for( i = 0; i < MAX_CB_JUMPTABLE; i++ ) { if( _CBJumpTable[i] == 0L ) { break; } } if( i == MAX_CB_JUMPTABLE ) { return( NULL ); } /* * build the callback code */ emitWhere = NULL; codesize = emitCode( argcnt, bytecnt, array, fn, is_cdecl ); emitWhere = malloc( codesize ); if( emitWhere == NULL ) { return( NULL ); } emitCode( argcnt, bytecnt, array, fn, is_cdecl ); /* * set up the callback jump table, and return the proper callback rtn */ _CBJumpTable[i] = (DWORD)emitWhere - *_DataSelectorBaseAddr + *_CodeSelectorBaseAddr; _CBRefsTable[i]++; /* increase reference count */ if( i > MaxCBIndex ) MaxCBIndex = i; *__32BitCallBackAddr = (FARPROCx)&__32BitCallBack; return( (char *)__16BitCallBackAddr - (i+1) * CB_CODE_SIZE ); } /* DoEmitCode */
void test_emitCode_given_index_97_should_translate_to_a_and_output_a(){ CEXCEPTION_T e; Dictionary *dictionary = dictionaryNew(100); OutStream out; int index = 97; streamWriteBits_Expect(&out, 97, 8); Try{ emitCode(dictionary, index, &out); }Catch(e){ TEST_ASSERT_EQUAL(ERR_EXCEEDING_DICTIONARY_SIZE, e); } }
IR Compile(Form* form) { string out; string tmp; if(form == NULL) error(form,"Can't emit code for the null form."); else if(isatom(form)) { if(val(form) == "quit") exit(0); else if(val(form) == "IR") { master.Program->dump(); nerror("Dumped IR."); } else if(val(form) == "debug") { master.debug = !master.debug; nerror("Debug mode is ",(master.debug?"on":"off"),"."); } else out = emitCode(form); } else out = emitCode(form/*,Top*/); /*for(unsigned long i = 0; i < master.Persistent.size(); i++) tmp += master.Persistent[i] + "\n";*/ for(unsigned long i = 0; i < master.CodeStack.size(); i++) tmp += master.CodeStack[i] + "\n"; out = "define " + latest_type() + " @entry(){\n" + out + "\nret " + latest_type() + " " + get_current_res() + "\n}"; out = tmp + out; string type = latest_type(); master.CodeStack.clear(); clear_reader(); return {out,type}; }
void test_emitCode_given_index_256_should_translate_to_ab_and_output_a_b(){ CEXCEPTION_T e; Dictionary *dictionary = dictionaryNew(100); dictionary->entries[0].code = "ab"; OutStream out; int index = 256; streamWriteBits_Expect(&out, 97, 8); streamWriteBits_Expect(&out, 98, 8); Try{ emitCode(dictionary, index, &out); }Catch(e){ TEST_ASSERT_EQUAL(ERR_EXCEEDING_DICTIONARY_SIZE, e); } }
int emitCALL(CodeBlock* codeBlock, WORD p, WORD q) { return emitCode(codeBlock, OP_CALL, p, q); }
int emitBP(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_BP, DC_VALUE, DC_VALUE); }
int emitGT(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_GT, DC_VALUE, DC_VALUE); }
int emitLE(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_LE, DC_VALUE, DC_VALUE); }
int emitCV(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_CV, DC_VALUE, DC_VALUE); }
int emitEQ(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_EQ, DC_VALUE, DC_VALUE); }
int emitML(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_ML, DC_VALUE, DC_VALUE); }
int emitNEG(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_NEG, DC_VALUE, DC_VALUE); }
int emitSB(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_SB, DC_VALUE, DC_VALUE); }
int emitAD(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_AD, DC_VALUE, DC_VALUE); }
int emitWLN(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_WLN, DC_VALUE, DC_VALUE); }
int emitWRI(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_WRI, DC_VALUE, DC_VALUE); }
int emitRC(CodeBlock* codeBlock) { return emitCode(codeBlock, OP_RC, DC_VALUE, DC_VALUE); }