void Optimizer::deleteUselessMovs(AsmCode& code){ for (int i = 0; i < code.size(); i++){ if (*code[i] != cmdMOV || !code[i]->usedRegister(EAX)) continue; AsmCmd2* cmd = dynamic_cast<AsmCmd2*>(code[i]); if (cmd->secondArg()->usedRegister(EAX)) continue; if (*cmd->firstArg() != EAX) continue; int idx = i + 1; bool deletingNedeed = true; while (idx < code.size() && deletingNedeed){ if (code[idx]->usedRegister(EAX)) if (*code[idx] != cmdMOV) deletingNedeed = false; else { AsmCmd2* tmp = dynamic_cast<AsmCmd2*>(code[idx]); if (tmp->secondArg()->usedRegister(EAX) || dynamic_cast<AsmIndirectArg*>(tmp->firstArg())) deletingNedeed = false; else break; } idx++; } if (deletingNedeed) code.deleteRange(i, i); } }
void BinOpNode::generateLvalue(AsmCode& code){ string value = token->Value; if (value == "+"){ SymbolType *type = left->getType(); if (dynamic_cast<ArraySymbol*>(type)) left->generateLvalue(code); else if (dynamic_cast<PointerSymbol*>(type)) left->generate(code); SymbolType *t = type->upType(); right->generate(code); code.add(_POP, _EAX) .add(_MOV, _EBX, to_string(t->byteSize())) .add(_IMUL, _EAX, _EBX) .add(_POP, _EBX) .add(_ADD, _EAX, _EBX) .add(_PUSH, _EAX); t = t->upType(); } else if (isAssing(token)){ generate(code); code.add(_POP, _EAX); left->generateLvalue(code); } else throw MyException("Compiler error"); }
void FuncCallNode::generate(AsmCode& code){ code.add(_SUB, _ESP, to_string(symbol->value->byteSize())); for (int i = args.size() - 1; i > -1; i--) args[i]->generate(code); code.add(_CALL, new AsmLabelArg("f_" + name->token->Value)) .add(_ADD, _ESP, to_string(symbol->params->byteSize())); }
void UnOpNode::generate(AsmCode & code) { SymbolType* type = operand->getType(); string op = token->Value; if (op == "++" || op == "--" || op == "*" || op == "&") operand->generateLvalue(code); else operand->generate(code); if (token->Value == "*"){ if (dynamic_cast<PointerSymbol*>(type)) code.add(_POP, _EAX) .add(_MOV, new AsmRegArg(_EBX), new AsmIndirectArg(_EAX)) .add(_PUSH, _EBX); else code.add(_POP, _EAX) .add(_MOV, new AsmRegArg(_EBX), new AsmIndirectArg(_EAX)) .add(_PUSH, new AsmIndirectArg(_EBX)); } else if (token->Value == "!"){ code.add(_POP, _EAX) .add(_XOR, _EBX, _EBX) .add(_CMP, _EAX, 0) .add(_SETE, _BL) .add(_PUSH, _EBX); } else if (token->Value == "+"){ } else if (token->Value == "-"){ code.add(_POP, _EAX) .add(_NEG, _EAX) .add(_PUSH, _EAX); } else if (token->Value == "++"){ generateOperationIncDec(type, code, _INC); } else if (token->Value == "--"){ generateOperationIncDec(type, code, _DEC); } }
void FuncSymbol::generate(AsmCode &code, const string &str) const { code.add(new AsmLabelArg("f_" + str)) .add(_PUSH, _EBP) .add(_MOV, _EBP, _ESP); body->generate(code); code.add(_MOV, _ESP, _EBP) .add(_POP, _EBP) .add(_RET, new AsmIntArg("0")); }
void IdentifierNode::generateLvalue(AsmCode &code) { if (var->global) code.add(_PUSH, new AsmMemoryArg("var_" + var->name, true)); else code.add(_MOV, _EAX, _EBP) .add(_MOV, _EBX, to_string(var->offset)) .add(_ADD, _EAX, _EBX); code.add(_PUSH, _EAX); }
void SymVarGlobal::Generate(AsmCode& asmCode, unsigned) const { if (type->GetSize() > 4) { GenerateLValue(asmCode, 0); asmCode.PushMemory(type->GetSize()); } else { asmCode.AddCmd(PUSH, AsmMemory(varLabel, 0, szDWORD)); } }
void IdentifierNode::generateLvalue(AsmCode &code) { if(var->global) code.add(cmdPUSH, makeArgMemory("var_" + var->name, true)); else code.add(cmdMOV, EAX, EBP) .add(cmdMOV, EBX, var->offset) .add(cmdADD, EAX, EBX) .add(cmdPUSH, EAX); }
bool PushPop2MovOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1]) && *cmd1 == cmdPUSH && *cmd2 == cmdPOP && !(cmd1->argument()->isMemory() && cmd2->argument()->isMemory())){ AsmCmd* optCmd = new AsmCmd2(cmdMOV, cmd2->argument(), cmd1->argument()); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
void IdentifierNode::generate(AsmCode &code) { int size = var->byteSize(); int steps = size / 4 + (size % 4 != 0); if (var->global) for (int i = 0; i < steps; i++) code.add(cmdPUSH, makeArgMemory("dword ptr [var_" + var->name + " + " + to_string(4 * (steps - i - 1)) +"]")); else for (int i = 0; i < steps; i++) code.add(cmdPUSH, makeIndirectArg(EBP, var->offset + 4 * (steps - i - 1))); }
static void generateOperationAssing(SymbolType * type, AsmCode & code, Commands cmd, Registers reg = _EAX) { code.add(_POP, _EBX) .add(_POP, _ECX); if (type->getType() == CharType) { code.add(_XOR, _EAX, _EAX) .add(_MOV, new AsmRegArg(_AL), new AsmIndirectArg(_ECX)); } else { code.add(_MOV, new AsmRegArg(_EAX), new AsmIndirectArg(_ECX)); } code.add(_XOR, _EDX, _EDX); if (cmd == _IDIV || cmd == _IMUL) code.add(cmd, _EBX); else code.add(cmd, _EAX, _EBX); if (type->getType() == CharType) { Registers byteReg = reg == _EAX ? _AL : _DL; code.add(_MOV, new AsmIndirectArg(_ECX), new AsmRegArg(byteReg)) .add(_XOR, reg, reg) .add(_MOV, new AsmRegArg(byteReg), new AsmIndirectArg(_ECX)); } else { code.add(_MOV, new AsmIndirectArg(_ECX), new AsmRegArg(reg)); } code.add(_PUSH, reg); }
bool AddZero2MovOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1], code[index + 2]) && *cmd1 == cmdMOV && *cmd2 == cmdMOV && *cmd3 == cmdADD && (*cmd1->secondArg() == 0 || *cmd2->secondArg() == 0)){ AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd3->firstArg(), *cmd1->secondArg() == 0 ? cmd2->secondArg() : cmd1->secondArg()); code.deleteRange(index, index + 2); code.insert(optCmd, index); return true; } return false; }
bool RegRegCMP2RegIntCmpOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1]) && *cmd1 == cmdMOV && cmd2 && *cmd2 == cmdCMP && *cmd1->firstArg() == cmd2->secondArg()){ AsmCmd2* optCmd = new AsmCmd2(cmdCMP, cmd2->firstArg(), cmd1->secondArg()); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
bool MovPush2PushOptimization::optimize(AsmCode& code, int index){ if (prepare(code[index], code[index + 1]) && *cmd1 == cmdMOV && *cmd1->firstArg() == EAX && *cmd2 == cmdPUSH && *cmd1->firstArg() == cmd2->argument()){ AsmCmd1* optCmd = new AsmCmd1(cmdPUSH, cmd1->secondArg()); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
static void generateOperation(AsmCode & code, Commands cmd, Registers reg = _EAX) { code.add(_POP, _EBX) .add(_POP, _EAX) .add(_XOR, _EDX, _EDX); if (cmd == _IDIV || cmd == _IMUL) code.add(cmd, _EBX); else code.add(cmd, _EAX, _EBX); code.add(_PUSH, reg); }
bool CompactAdditionOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1], code[index + 2]) && *cmd1 == cmdMOV && *cmd2 == cmdMOV && *cmd1->firstArg() == EBX && *cmd1->secondArg() == cmd2->firstArg() && *cmd3 == cmdADD && *cmd3->firstArg() == cmd2->firstArg() && *cmd3->secondArg() == cmd1->firstArg()){ AsmCmd2* optCmd = new AsmCmd2(cmdMOV, makeArg(EBX), cmd2->secondArg()); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
bool MovChainOptimization::optimize(AsmCode& code, int index){ if (prepare(code[index], code[index + 1]) && *cmd1 == cmdMOV && *cmd1->firstArg() == EAX && *cmd2 == cmdMOV && *cmd2->secondArg() == cmd1->firstArg() && !(cmd1->secondArg()->isMemory() && cmd2->firstArg()->isMemory()) ){ AsmCmd* optCmd = new AsmCmd2(cmdMOV, cmd2->firstArg(), cmd1->secondArg()); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
bool PopToUpPushToDown::Action(AsmCode& code, AsmCmd1* cmd, int i, int inc) { int j = i; while (0 < j && j + 1 < code.Size() && !UsesStack(code[j + inc]) && !IsArgument(cmd->GetArgument(), code[j + inc])) { j += inc; } code.Move(i, j); return j != i; }
bool Neg2MovOppositeOptimization::optimize(AsmCode& code, int index){ if (prepare(code[index], code[index + 1]) && *cmd1 == cmdMOV && *cmd1->firstArg() == EAX && *cmd2 == cmdNEG && *cmd2->argument() == EAX && dynamic_cast<AsmImmediateArg*>(cmd1->secondArg())){ int val = dynamic_cast<AsmImmediateArg*>(cmd1->secondArg())->value; AsmCmd2* optCmd = new AsmCmd2(cmdMOV, makeArg(EAX), makeArg(-val)); code.deleteRange(index, index + 1); code.insert(optCmd, index); return true; } return false; }
void Optimizer::pushDownPopUp(AsmCode& code){ for (int i = 0; i < code.size(); i++){ AsmCmd1* cmd = dynamic_cast<AsmCmd1*>(code[i]); int j = i; if (cmd && *cmd == cmdPUSH){ while (j + 1 < code.size() && !code[j + 1]->changeStack() && !code[j + 1]->operateWith(cmd->argument())) j++; code.move(i, j); } else if (cmd && *cmd == cmdPOP) { while (j - 1 > -1 && !code[j - 1]->changeStack() && !code[j - 1]->operateWith(cmd->argument())) j--; code.move(i, j); } } }
void SymVarConst::GenerateValue(AsmCode& asm_code) const { if (value.GetType() == INT_CONST) { asm_code.AddCmd(ASM_PUSH, value.GetIntValue()); } else if (value.GetType() == REAL_CONST) { stringstream s; s << value.GetName(); float f; int* p = (int*)&f; s >> f; asm_code.AddCmd(ASM_PUSH, *p); }
bool MultIntByInt2MovOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1], code[index + 2]) && *cmd1 == cmdMOV && *cmd2 == cmdMOV && *cmd1->firstArg() == EAX && *cmd2->firstArg() == EBX && cmd1->secondArg()->isImmediate() && cmd2->secondArg()->isImmediate() && *cmd3 == cmdIMUL){ int val1 = dynamic_cast<AsmImmediateArg*>(cmd1->secondArg())->value, val2 = dynamic_cast<AsmImmediateArg*>(cmd2->secondArg())->value; AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd3->firstArg(), makeArg(val1 * val2)); code.deleteRange(index, index + 2); code.insert(optCmd, index); return true; } return false; }
//----------------------------------------------------------------------------- bool AddSubZero::Optimize(AsmCode& code, int index) { if (index == code.Size()) { return false; } AsmCmd2* cmd = dynamic_cast<AsmCmd2*>(code[index]); if (cmd && (*cmd == cmdSUB || *cmd == cmdADD) && *cmd->GetSecond() == "0") { code.Delete(index); return true; } return false; }
bool AddSubESPZeroOptimization::optimize(AsmCode &code, int index){ if (prepare(code[index]) && *cmd1->firstArg() == ESP && *cmd1->secondArg() == 0){ code.deleteRange(index, index); return true; } return false; }
static void generateOperationShift(AsmCode & code, Commands cmd) { code.add(_POP, _EAX) .add(_POP, _EBX) .add(_MOV, _ECX, _EAX) .add(cmd, _EBX, _CL) .add(_PUSH, _EBX); }
bool Jmp2NextLineOptimization::optimize(AsmCode& code, int index){ if (prepare(code[index], code[index + 1]) && *cmd1->argument() == cmd2->label){ code.deleteRange(index, index); return true; } return false; }
void ArrNode::generate(AsmCode &code){ generateLvalue(code); code.add(_PUSH, new AsmIndirectArg(_EAX)) .add(_POP, _EAX) .add(_POP, _ECX) .add(_PUSH, new AsmRegArg(_EAX)); }
bool PushPop2NilOptimization::optimize(AsmCode& code, int index){ if( prepare(code[index], code[index + 1]) && *cmd1 == cmdPUSH && *cmd2 == cmdPOP && cmd1->argument()->isRegister() && *cmd1->argument() == cmd2->argument()) { code.deleteRange(index, index + 1); return true; } return false; }
static void generateCmp(AsmCode & code, Commands cmd) { code.add(_POP, _EBX) .add(_POP, _EAX) .add(_XOR, _ECX, _ECX) .add(_CMP, _EAX, _EBX) .add(cmd, _CL) .add(_PUSH, _ECX); }
static void generateOperationIncDec(SymbolType* type, AsmCode & code, Commands cmd) { code.add(_POP, _EAX); if (type->getType() == CharType) { code.add(_XOR, _EBX, _EBX) .add(_MOV, new AsmRegArg(_BL), new AsmIndirectArg(_EAX)); } else { code.add(_MOV, new AsmRegArg(_EBX), new AsmIndirectArg(_EAX)); } code.add(cmd, _EBX); if (type->getType() == CharType) { code.add(_MOV, new AsmIndirectArg(_EAX), new AsmRegArg(_BL)) .add(_XOR, _EBX, _EBX) .add(_MOV, new AsmRegArg(_BL), new AsmIndirectArg(_EAX)) .add(_PUSH, new AsmRegArg(_EAX)); } else { code.add(_MOV, new AsmIndirectArg(_EAX), new AsmRegArg(_EBX)); } code.add(_PUSH, _EBX); }