// 構文木をトレースする static void traceTree(int node) { if (node==SyNULL) return; // 何も無い int ty = syGetType(node); if (ty==SyIF) genIf(node); // if 文 else if (ty==SyELS) genEls(node); // if-else 文 else if (ty==SyWHL) genWhl(node); // while 文 else if (ty==SyDO) genDo(node); // do-while 文 else if (ty==SyBRK) genBrk(node); // break 文 else if (ty==SyCNT) genCnt(node); // continue 文 else if (ty==SyRET) genRet(node); // retrun 文 else if (ty==SyBLK || ty==SySEMI) { // ブロック traceTree(syGetLVal(node)); // 先に左側をコード生成 traceTree(syGetRVal(node)); // 次に右側をコード生成 } else if (ty==SyVAR) { // ローカル変数宣言 ; // 特にやることがない } else { // 式文 struct Expr *c = newExpr(); // 式の状態を管理するデータ genBoolExpr(node, c); // 式を処理する pop(c); // スタックにあれば捨てる free(c); // 管理データを解放 } }
// generate code for a captured BB void generate(Rewriter* r, CBB* cbb) { uint8_t* buf; uint64_t buf0; int used, i, usedTotal; if (cbb == 0) return; if (r->cs == 0) return; if (r->showEmuSteps) printf("Generating code for BB %s (%d instructions)\n", cbb_prettyName(cbb), cbb->count); usedTotal = 0; buf0 = (uint64_t) reserveCodeStorage(r->cs, 0); // remember start address for(i = 0; i < cbb->count; i++) { Instr* instr = cbb->instr + i; buf = reserveCodeStorage(r->cs, 15); if (instr->ptLen > 0) { used = genPassThrough(buf, instr); } else { switch(instr->type) { case IT_ADD: used = genAdd(buf, &(instr->src), &(instr->dst)); break; case IT_CLTQ: used = genCltq(buf, instr->vtype); break; case IT_CQTO: used = genCqto(buf, instr->vtype); break; case IT_CMP: used = genCmp(buf, &(instr->src), &(instr->dst)); break; case IT_DEC: used = genDec(buf, &(instr->dst)); break; case IT_IMUL: used = genIMul(buf, &(instr->src), &(instr->dst)); break; case IT_IDIV1: used = genIDiv1(buf, &(instr->dst)); break; case IT_INC: used = genInc(buf, &(instr->dst)); break; case IT_XOR: used = genXor(buf, &(instr->src), &(instr->dst)); break; case IT_OR: used = genOr(buf, &(instr->src), &(instr->dst)); break; case IT_AND: used = genAnd(buf, &(instr->src), &(instr->dst)); break; case IT_SHL: used = genShl(buf, &(instr->src), &(instr->dst)); break; case IT_SHR: used = genShr(buf, &(instr->src), &(instr->dst)); break; case IT_SAR: used = genSar(buf, &(instr->src), &(instr->dst)); break; case IT_LEA: used = genLea(buf, &(instr->src), &(instr->dst)); break; case IT_MOV: case IT_MOVSX: // converting move used = genMov(buf, &(instr->src), &(instr->dst)); break; case IT_CMOVO: case IT_CMOVNO: case IT_CMOVC: case IT_CMOVNC: case IT_CMOVZ: case IT_CMOVNZ: case IT_CMOVBE: case IT_CMOVA: case IT_CMOVS: case IT_CMOVNS: case IT_CMOVP: case IT_CMOVNP: case IT_CMOVL: case IT_CMOVGE: case IT_CMOVLE: case IT_CMOVG: used = genCMov(buf, instr->type, &(instr->src), &(instr->dst)); break; case IT_POP: used = genPop(buf, &(instr->dst)); break; case IT_PUSH: used = genPush(buf, &(instr->dst)); break; case IT_RET: used = genRet(buf); break; case IT_SUB: used = genSub(buf, &(instr->src), &(instr->dst)); break; case IT_TEST: used = genTest(buf, &(instr->src), &(instr->dst)); break; case IT_HINT_CALL: case IT_HINT_RET: used = 0; break; default: assert(0); } } assert(used < 15); instr->addr = (uint64_t) buf; instr->len = used; usedTotal += used; if (r->showEmuSteps) { printf(" I%2d : %-32s", i, instr2string(instr, 1, 0)); printf(" (%s)+%lx %s\n", cbb_prettyName(cbb), instr->addr - buf0, bytes2string(instr, 0, used)); } useCodeStorage(r->cs, used); } if (r->showEmuSteps) { if (instrIsJcc(cbb->endType)) { assert(cbb->nextBranch != 0); assert(cbb->nextFallThrough != 0); printf(" I%2d : %s (%s),", i, instrName(cbb->endType, 0), cbb_prettyName(cbb->nextBranch)); printf(" fall-through to (%s)\n", cbb_prettyName(cbb->nextFallThrough)); } } // add padding space after generated code for jump instruction buf = useCodeStorage(r->cs, 10); cbb->size = usedTotal; // start address of generated code. // if CBB had no instruction, this points to the padding buffer cbb->addr1 = (cbb->count == 0) ? ((uint64_t)buf) : cbb->instr[0].addr; }