/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package targets.mips; import ast.Node; import common.Code; import common.DataLayout; import common.Instruction; import common.IvannosysTargetArch; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * MipS tranSlation * * @author EUGENIO CARVALHO */ public class Gen extends API.TargetGen { protected ArrayList returnRegisters; protected HashMap AddressCalculated = new HashMap<>(); // protected AllocatorMipsProcessor allocation = new AllocatorMipsProcessor(); protected HashMap comments = new HashMap() { { put("beq", "branch if equals"); put("bne", "branch if not equals"); put("blez", "branch if register <= 0"); put("bltz", "branch if register < 0"); put("bgez", "branch if register >= 0"); put("bgtz", "branch if register > 0"); } }; protected HashMap ctrlDataUpdate = new HashMap<>(); protected Integer WORD_INC = 4; public Gen() { super("mips"); } public void Init() throws Exception { getTarget().Template(new MipsTemplate()); } @Override public void TranslateLabel(Instruction inst) { Add(new Instruction() .Set("type", "label") .Set("format", "norender") .Set("tac.position", inst.Get("block.position")) .Set("label", inst.Get("label"))); getTarget().RegisterLabelAddress(inst.Get("label")); } @Override public void TranslateCopy(Instruction inst) throws Exception { Copy(inst, inst.Get("reg.dst")) .Set("tac.position", inst.Get("block.position")) .Set("comment", "copy " + inst.Get("dst") + " ← " + inst.Get("p1")); } @Override public void TranslateAssign(Instruction inst) throws Exception { String instruction = Mips.InstructionByOperator(inst); String rd = inst.Get("reg.dst"), dst = inst.Get("dst"); Instruction ninst = new Instruction(instruction).Set("tac.position", inst.Get("block.position")); switch (Mips.Codops.get(instruction).Get("type")) { //addi, addiu, slti, sltiu case "I": ninst.Set("rt", rd); // System.out.println("Assign:" + inst); if (inst.eq("p2value", "true")) { String op = inst.Get("op"); LoadParam(inst, "p1"); ninst.Set("offset", (op.equals("-") ? "-" : "") + inst.Get("p2")) .Set("rs", inst.Get("reg.p1")); } else { LoadParam(inst, "p2"); ninst.Set("offset", inst.Get("p1")) .Set("rs", inst.Get("reg.p2")); } break; // mult, divu, sgtu ,sltu // sra, srl, sll case "R": // System.out.println("Translate assign:" + inst + "-" + Mips.Codops.Get(instruction).Get("type")); // System.out.println("SLL:" + inst); LoadParam(inst); // if (ninst.in("inst", "sll,srl,sra".split(","))) { rd = inst.Get("reg.dst"); ninst.Set("sa", inst.Get("p2")) .Set("rt", inst.Get("reg.p1")); } else { ninst.Set("rs", inst.Get("reg.p1")) .Set("rt", inst.Get("reg.p2")); } ninst.Set("rd", rd); // System.out.println("inst["+rd+"]" + inst + ":" + ninst); break; } Add(ninst); // Verifica se a expr possui overflow String overflow = Mips.Instruction(instruction).Get("overflow"); if (!overflow.equals("")) { Add(new Instruction("R", overflow) .Set("rd", rd) .Set("tac.position", inst.Get("block.position")) ); } // StoreResult(inst, rd, dst); } @Override public void TranslateJump(Instruction inst) throws Exception { Add(new Instruction("J", "j") .copy("label", inst) .Set("comment", inst.getText()) .Set("tac.position", inst.Get("block.position")) ); AddNop(); } @Override public void TranslateCall(Instruction inst) throws Exception { // allocation.registers.ResetArgs(); // Before load params // Copy(inst, returnRegisters.remove(2)) // .Set("IR.position", inst.Get("block.position")) // .Set("comment", "push param"); // System.out.println("Call" + inst); ResetReturnArgs(); try { Instruction retur; LinkedList intructions = getIR().Block().Instructions(); int base = intructions.indexOf(inst); for (int i = inst.getInt("nump"); i > 0; i--) { retur = intructions.get(base - i); Copy(retur, returnRegisters.remove(2)) .Set("tac.position", retur.Get("global.position")) .Set("comment", "push param"); } } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } Add(new Instruction("J", "jal") .Set("label", inst.Get("funcname")) .Set("comment", "jump to <" + inst.Get("funcname") + ">") .Set("tac.position", inst.Get("block.position")) ); // After store results // Restaura o array de registradores de retorno para fazer o pop dos returns ResetReturnArgs(); AddNop(); } @Override public void TranslatePushReturn(Instruction inst) { // Tratado no metodo 'TranslateReturn' } @Override public void TranslateReturn(Instruction inst) { // Restaura o array de registradores de retorno ResetReturnArgs(); try { Instruction retur; LinkedList intructions = getIR().Block().Instructions(); int base = intructions.indexOf(inst); for (int i = inst.getInt("p1"); i > 0; i--) { retur = intructions.get(base - i); // System.out.println("Return:" + retur); Copy(retur, returnRegisters.remove(0)) .Set("tac.position", retur.Get("global.position")) .Set("comment", "push return"); } } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void TranslatePushParam(Instruction inst) { // Tratado no metodo 'TranslateCall' } @Override public void TranslatePopReturn(Instruction inst) { try { String p1 = inst.Get("p1"), reg = returnRegisters.remove(0); // Se for uma variavel temporaria if (p1.contains("_T")) { CopyReg(reg, inst.Get("reg.p1")); } else { StoreWord(reg, FrameRegister(p1), getTarget().Block().Data().Offset(p1)); } // System.out.println("Translate pop return" + inst); } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void TranslatePopParam(Instruction inst) { try { // todo - resetar args // System.out.println("PopParam:" + inst); String p1 = inst.Get("p1"); // O indice é 2 por conta dos dois primeiros registradores {v0, v1} // System.out.println("PopParams:" + inst); int offset = getTarget().Block().Data().Offset(p1); StoreWord(returnRegisters.remove(2), FrameRegister(p1), offset) .Set("tac.position", inst.Get("block.position")) .Set("comment", "pop param"); // System.out.println("POPpARAM:" + inst); // LoadWord(inst.Get("reg.p1"), "fp", offset); } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void TranslateBranch(Instruction inst) throws Exception { String instruction = Mips.InstructionByOperator(inst); LoadParam(inst); String rs = inst.Get("reg.p1"); String rt = inst.Get("reg.p2"); Instruction I = new Instruction("I", instruction) .Set("label", inst.Get("funcname")); switch (instruction) { case "beq": // == {[inst]}' ' {[rt]},{[rs]},{immediate} case "bne": // != I.Set("rs", rs).Set("rt", rt); break; case "blez": // <= 0{[inst]}' ' {[rs]},{immediate} case "bltz": // < 0 case "bgez": // >= 0 case "bgtz": // > 0 Add(new Instruction("R", "subu")// Rd <-- [Rs] - [Rt]; .Set("rs", rs) .Set("rt", rt) .Set("rd", "v0") .Set("tac.position", inst.Get("block.position")) .Set("comment", "") ); I.Set("rs", "v0"); break; } Add(I).Set("label", inst.Get("label")) .Set("tac.position", inst.Get("block.position")) .Set("comment", comments.get(instruction)); AddNop(); // System.out.println("Translate branch:" + I); } protected void AddNop() throws Exception { Add(Mips.Instruction("nop").copy()); } @Override public void Prolog(String id) throws Exception { DataLayout data = getTarget().Block().Data(); // Copia os dados para block target //Updata size in 4 bytes CopyData( // data.values(), // getIR().Block().Data().values() data, getIR().Block().Data() ); // Adiciona o label Add(new Instruction() .Set("type", "label") .Set("format", "label") .Set("label", id) ); // Aloca o espaco da pilha Instruction alloc = Copy("sp", "sp", "-" + data.Size()) .Set("comment", "prolog| push stack frame"); if (!getTarget().Block().getName().equals("main")) { // Restaura o fp // Restaura o ra // boolean call = getIR().Block().HasCall(); if (getIR().Block().HasCall()) { int newvars = 0; for (String reg : new String[]{"fp", "ra"}) { data.Add(reg, new Node() .Set("type", "int") .S("size", 1 * WORD_INC), 1); newvars -= WORD_INC; StoreWord(reg, "sp", data.Offset(reg)) .Set("comment", "prolog| backup " + reg); } alloc.sum("offset", newvars); } // System.out.println("PROLOG:(" + newvars + ")" + alloc); } // System.out.println("Activation Registry:()\n" + data); if (alloc.getInt("offset", 0) != 0) { // Copia o sp para o fp CopyReg("sp", "fp").Prepend("comment", "prolog|"); ResetReturnArgs(); } else { getTarget().Block().Remove(alloc); } } /** * Encerra a chamada de uma funcao * * @param id * @throws Exception */ @Override public void Epilog(String id) throws Exception { DataLayout data = getTarget().Block().Data(); if (!getTarget().Block().getName().equals("main")) { // Restaura o fp // Restaura o ra boolean call = getIR().Block().HasCall(); for (String reg : new String[]{"fp", "ra"}) { if (call) { LoadWord(reg, "sp", data.Offset(reg)).Set("comment", "epilog| restore " + reg); } } // Desaloca a pilha Copy("sp", "sp", data.Size()) .Set("comment", "epilog|pop stack frame"); CopyReg("sp", "fp") .Set("comment", "epilog|pop stack frame"); // if (getIR().Block().HasCall()) { Add(new Instruction("jr") .Set("rs", "ra") .Set("comment", "epilog|return")); // }[] } else { Add(Mips.Instruction("stop").copy()); } } @Override public void TranslateIndexedAssignment(Instruction inst) throws Exception { //Fase de leitura IndexedRead(inst); //Fase de atribuicao IndexedDest(inst); } @Override public void TranslateUnary(Instruction inst) throws Exception { // Carrega o valor se nao esta em registrador // System.out.println("Translate Unary:" + inst); switch (inst.Get("op")) { case "-": // Retorna o valor negado 10 -> -10 Add(new Instruction("subu")// Rd <-- [Rs] - [Rt]; .Set("rd", inst.Get("reg.dst")) .Set("rs", "zero") .Set("rt", inst.Get("reg.p1")) .Set("comment", "negation arith") .Set("tac.position", inst.Get("block.position")) ); break; case "!": // XOR ( 0 1 -> 1) XOR( 1 1 -> 0) Add(new Instruction("xori") // Rt <-- [Rs] AND (016 || [I15..0]); ; .Set("rt", inst.Get("reg.dst")) .Set("rs", inst.Get("reg.p1")) .Set("offset", "1") .Set("comment", "negation bool") .Set("tac.position", inst.Get("block.position")) ); break; // case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break;// case "*": // Copia do conteudo do ponteiro // // case "&": // Copia do endereco da variavel // break; } } @Override public void TranslateLoad(Instruction inst) throws Exception { String addr = inst.Get("p1"); // System.out.println("Load " + addr + " on block "); LoadWord( inst.Get("reg.p1"), FrameRegister(addr), getTarget().Block().Data().Offset(addr) ); } @Override public void TranslateStore(Instruction inst) throws Exception { String addr = inst.Get("p1"); // System.out.println("Store " + addr + " on block "); StoreWord( inst.Get("reg.p1"), FrameRegister(addr), getTarget().Block().Data().Offset(addr) ); } /** * Traducao de intrucoeS do tipo * * - x = &a - copia do endereco de uma varaivel
* - x = *b - x recebe o conteudo da variavel referenciada por b
* - *x = y - conpia o conteudo de y para o endereco armazenado em x * * @param inst * @throws Exception */ @Override public void TranslatePointerAssignment(Instruction inst) throws Exception { String p1 = inst.Get("p1"), dst = inst.Get("dst"), regdst = inst.Get("reg.dst"), regp1 = inst.Get("reg.p1"); switch (inst.Get("op")) { case "&": // Lendo o endereco de um ponteiro Copy(regp1, FrameRegister(p1), getIR().Block().Data().Offset(p1) ) .Set("tac.position", inst.Get("block.position")) .Set("comment", "copy address of " + p1); System.out.println("PointerAssi&:" + inst); // Se nao fez o store // if (StoreResult(inst, regp1, dst) == null) { // CopyReg(regp1, regdst); // .Set("comment", "store content of " + regdst + " in " + dst); // } break; case "*": // Lendo o conteudo de um ponteiro /** * Carrega o valor contido no ponteiro
* Utiliza o valor como endereço em um segundo load que carrega * o dado
* lw ${p1},12($fp)
* lw ${dst},0(${p1}) $s
*/ LoadWord(regp1, FrameRegister(p1), getIR().Block().Data().Offset(p1)) .Set("tac.position", inst.Get("block.position")) .Set("comment", "load address stored in " + p1); LoadWord(regdst, regp1, "0") .Set("tac.position", inst.Get("block.position")) .Set("comment", "load content of address stored in " + regp1); /*Se for a ultima operacao de escrita nessa variavel salva em memoria*/ // Instruction store = StoreResult(inst, regdst, dst); // if (store != null) { // store.Set("comment", "store content of " + regdst + " in " + dst); // } break; default: // Atribuicao a um ponteiro LoadParam(inst); /** * Carrega o valor dentro do endereco do ponteiro
* lw ${p1},12(${fp|gp})
* lw ${dst},0(${p1}) $s
* conteudo da variavel referenciada */ LoadWord(regdst, FrameRegister(dst), getIR().Block().Data().Offset(dst)) .Set("tac.position", inst.Get("block.position")) .Set("comment", "load address stored in " + dst); // Grava o valor do registrador na memoria StoreWord(regp1, regdst, "0") .Set("tac.position", inst.Get("block.position")) .Set("comment", "store content of " + regp1 + " in *" + dst); } } // public void CopyData(LinkedHashMap dst, LinkedHashMap src) throws Exception { public void CopyData(DataLayout dst, DataLayout src) throws Exception { Node value; LinkedHashMap svalues = src.values(), dvalues = dst.values(); for (Map.Entry x : svalues.entrySet()) { value = x.getValue().copy(); value.S("size", value.getInt("size") * WORD_INC); // System.out.println("Copy:[" + x.getKey() + "][" + value.Get("id") + "]" + value.Get("size") + "\n" + value); // dvalues.put(x.getKey(), value); dst.Set(x.getKey(), value); } } public IvannosysTargetArch SetTAC(Code tac) { try { this.IR = tac; Init(); // getTarget().AfterTranslateBlock("copy.dep", new CopyDeps(tac)); // CopyData(target.GlobalData().values(), IR.GlobalData().values()); CopyData( target.GlobalData(), tac.GlobalData() ); } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } return this; } /** * Criar uma inStrucao que copia o valor ou conteudo do regiStrador para o * regiStrador 'r' * * @param inst * @param push * @param rt */ protected Instruction Copy(Instruction inst, String rt) { Instruction c; if (inst.eq("p1value", "true")) { // andi Rt,Rs,immediate | Rt <-- [Rs] + ([I15]16 || [I15..0]); c = Copy(rt, "zero", inst.Get("p1")); } else { // addu Rd,Rs,Rt | Rd <-- [Rs] + [Rt]; LoadParam(inst, "p1"); c = CopyReg(inst.Get("reg.p1"), rt); } return c.Set("tac.position", inst.Get("block.position")); } protected void IndexedRead(Instruction inst) { // Se a fonte é indexada if (inst.eq("src_indexed", "true")) { try { int offset = getTarget().Block().Data().Offset(inst.Get("p1")); String p1 = inst.Get("p1"), rt = inst.Get("reg.p1"), rs = FrameRegister(p1); // System.out.println("Indexed read:" + inst); if (!inst.isNumber("p1.indice")) { String rd = inst.Get("reg.p1.indice"); if (!AddressCalculated.containsKey(p1)) { Add(new Instruction("addu") .Set("rd", rd) .Set("rs", rs) .Set("rt", rd)) .Set("tac.position", inst.Get("block.position")); AddressCalculated.put(p1, rs); } rs = rd; } // Carrega o conteudo enderecado em rt para rt LoadWord(rt, rs, offset).Set("tac.position", inst.Get("block.position")); AddNop(); } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } else { // Se não é indexada carrega o parametro normalmente LoadParam(inst); } } /** * FaSe de atribuicao * * @param inst */ protected void IndexedDest(Instruction inst) { // System.out.println("Indexeds:" + inst); String regp1 = inst.Get("reg.p1"), regdst = inst.Get("reg.dst"); // Valor atribuido é indexado // 1 - Verificar se deve ser armazenado ou copiado boolean dstIndexed = inst.eq("dst_indexed", "true"); if (dstIndexed || inst.eq("reg.dst.store", "true")) { try { // deve ser armazenado String dst = inst.Get("dst"), rs = FrameRegister(dst), comment; int offset = getTarget().Block().Data().Offset(dst); if (dstIndexed) { if (!inst.isNumber("dst.indice")) { // Offset agora deve ser 0 pois o registrador conterá o endereco completo // offset = 0; String rd = inst.Get("reg.dst.indice"); if (!AddressCalculated.containsKey(dst)) { Add(new Instruction("addu") .Set("rd", rd) .Set("rs", rs) .Set("rt", rd) .Set("tac.position", inst.Get("block.position")) ); AddressCalculated.put(dst, rs); } rs = rd; } comment = "store in loaded address"; } else { comment = "store in " + dst; }// System.out.println("Inst:" + inst); StoreWord(regp1, rs, offset) .Set("tac.position", inst.Get("block.position")) .Set("comment", comment); Instruction n = Next(); if (n != null && (n.eq("rs", regp1) || n.eq("rts", regp1))) { AddNop(); } } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } else { // deve ser copiado CopyReg(regp1, regdst) .Set("tac.position", inst.Get("block.position")); } } /** * Verificar Se o valor da atribuição ja eSta em regiStrador. CaSo não * eSteja o valor é carregado e o valor retornado é o nome do regiStrador * * @param inst * @param param * @return */ protected String LoadParam(Instruction inst) { return LoadParam(inst, "p1,p2"); } protected String LoadParam(Instruction inst, String params) { return LoadParam(inst, params.split(",")); } protected String LoadParam(Instruction inst, String[] params) { String pname; for (String param : params) { if (!inst.Has("reg." + param + ".load")) { continue; } Instruction Ninst = new Instruction(); pname = inst.Get(param); if (inst.eq(param + "value", "true")) { // System.out.println("pname:" + pname); if (pname.equals("0")) { inst.Set("reg." + param, "zero"); continue; } Ninst.Set("inst", "addiu") // R[$rt] ← {(imm)[15:0], 0 × 16} .Set("rs", "zero") .Set("rt", inst.Get("reg." + param)) .Set("offset", pname); } else { try { Ninst.Set("inst", "lw") // R[$rt] ← Mem4B(R[$rs] + SignExt16b(imm)) .Set("rt", inst.Get("reg." + param)) .Set("rs", FrameRegister(pname)) .Set("comment", "load address stored in " + pname) .Set("offset", getTarget().Block().Data().Offset(pname)); } catch (Exception ex) { Logger.getLogger(Gen.class.getName()).log(Level.SEVERE, null, ex); } } Add(Ninst.Set("tac.position", inst.Get("block.position"))); // x.Set("reg." + param, reg); } return null; } /** * Copia o valor do regiStrador Src para o dSt * * @param src * @param dst * @return */ protected Instruction CopyReg(String src, String dst) { return Add(new Instruction("addu") .Set("rs", "zero") .Set("rt", src) .Set("rd", dst) .Set("comment", "copy " + dst + " ← " + src)); } protected Instruction Copy(String rt, String rs, int offset) { return Copy(rt, rs, "" + offset); } protected Instruction Copy(String rt, String rs, String offset) { return Add(new Instruction("addiu") // lw $rt, imm($rs) .Set("rt", rt) .Set("rs", rs) .Set("offset", offset) .Set("comment", "copy " + rs + " ← " + rt) ); } protected Instruction StoreWord(String rt, String rs, int offset) throws Exception { return StoreWord(rt, rs, "" + offset); } protected Instruction StoreWord(String rt, String rs, String offset) throws Exception { Instruction n = Next(); Instruction sw = Add(new Instruction("sw") .Set("rt", rt) .Set("rs", rs) .Set("offset", offset)); // System.out.println("N:" + n); // Se a proxima instrução depende do valor armazenado if (n != null && (n.eq("reg.p1", rt) || n.eq("reg.p2", rt))) { AddNop(); } return sw; } protected Instruction LoadWord(String rt, String rs, int offset) throws Exception { return LoadWord(rt, rs, "" + offset); } protected Instruction LoadWord(String rt, String rs, String offset) throws Exception { Instruction n = Next(); Instruction lw = Add(new Instruction("lw") // lw $rt, imm($rs) .Set("rt", rt) .Set("rs", rs) .Set("offset", offset)); // Se a proxima instrução depende do valor armazenado if (n != null && (n.eq("reg.p1", rt) || n.eq("reg.p2", rt))) { AddNop(); } return lw; } @Override protected Instruction Add(Instruction inst) { try { if (!inst.eq("type", "label")) { getTarget().PositionInc(); Instruction definiction = Mips.Instruction(inst.Get("inst")); inst.Merge("sa,type,inst,codop,func,format", definiction); } } catch (Exception ex) { Logger.getLogger(Gen.class .getName()).log(Level.SEVERE, null, ex); } // System.out.println("Add:" + inst); return super.Add(inst); //To change body of generated methods, choose Tools | Templates. } protected String FrameRegister(String var) { return var.contains("_G") ? "gp" : "fp"; } private void ResetReturnArgs() { returnRegisters = new ArrayList() { { add("v0"); add("v1"); add("a0"); add("a1"); add("a2"); add("a3"); } }; } }