/* * 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 API; import common.Block; import common.Code; import common.DataLayout; import common.Instruction; import common.IvannosysTargetArch; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author EUGENIO CARVALHO */ public abstract class TargetGen implements IvannosysTargetArch { protected HashMap exportMethods = new HashMap<>(); protected Code target; protected Code IR; protected Instruction prev = null, next = null; protected Instruction currentIrInstruction; protected Instruction currentTargetInstruction; public TargetGen(String id) { BaseGenInit(id); } /** * Like Sprintf * * @param format * @param args * @return */ protected String F(String format, Object... args) { return String.format(format, args); } /** * Retorna o contexto do bloco atual * * @return */ public DataLayout Context() { return Context(""); } /** * Retorna o contexto do bloco atual
* Se var contem "G" retorna o contexto global * * @param var * @return */ public DataLayout Context(String var) { if (var.contains("G")) { return IR.GlobalContext(); } return IR.Block().Context(); } public common.Offset Offset(String var) throws Exception { return Context(var).Offset(var); } public void BaseGenInit(String id) { target = new Code(id); } public Code getTarget() { return target; } public void setTarget(Code target) { this.target = target; } public Code getIR() { return IR; } public ExportInterface GetExportMethod(String id) throws Exception { id = id.trim(); if (!exportMethods.containsKey(id)) { Set set = exportMethods.keySet(); String[] valids = new String[set.size()]; set.toArray(valids); throw new Exception(String.format( "O método de exportação '%s' não foi definido no alvo '%s'. Métodos disponiveis: %s", id, target.Name(), Utils.Join(valids, ", "))); } return exportMethods.get(id); } public HashMap GetExportMethods() { return exportMethods; } public IvannosysTargetArch Init(Code tac) throws Exception { // Verifica se o codigo gerado vai ser util caso contrario aborta o processo; ArrayList methods = BuildParams.Get("export"); if (methods.isEmpty()) { throw new Exception(String.format("Nenhum método de exportação definido para o alvo '%s'", target.Name())); } IR = tac; // target.GlobalContext().copy(tac.GlobalContext()); target.Parent = IR; return this; } protected Instruction Add(Instruction inst) throws Exception { if (currentIrInstruction != null) { inst.Set("tac.position", currentIrInstruction.Get("block.position")); } target.Block().Add(inst); currentTargetInstruction = inst; return inst; } public TargetGen AddExportOption(String id, ExportInterface exp) { exportMethods.put(id.trim(), exp); return this; } @Override public IvannosysTargetArch Format() { try { String code = target.Dump(); System.out.println("Target[" + target.Name() + "]:\n" + code); } catch (Exception ex) { Logger.getLogger(TargetGen.class.getName()).log(Level.SEVERE, null, ex); } return this; } @Override public IvannosysTargetArch Compile() { try { // Traduz o codigo intermediario para o alvo Translate(); } catch (Exception ex) { Logger.getLogger(TargetGen.class.getName()).log(Level.SEVERE, null, ex); } return this; } protected void Translate() throws Exception { String targetID = target.Name(), id; target.Parent = IR; Block block; Middleware.Trigger(target, targetID, "before.translate"); for (Map.Entry b : IR.Blocks().entrySet()) { id = b.getKey(); block = b.getValue(); if (block.Type() == Block.TYPE_CTRL) { continue; } IR.Use(id); target.OpenBlock(id); Middleware.Trigger(target, targetID, "before.translate.block"); Prolog(id); TranslateBlock(block); Epilog(id); target.CloseBlock(); Middleware.Trigger(target, targetID, "after.translate.block"); } target.UpdatePositions(); Middleware.Trigger(target, targetID, "after.translate"); } @Override public IvannosysTargetArch Export() throws Exception { ArrayList methods = BuildParams.Get("export"); for (String method : methods) { GetExportMethod(method).Exec(IR, target); } return this; } protected void TranslateBlock(Block b) throws Exception { // System.out.println("Translate block:" + b.getName() + "::" + b.Instructions().size()); LinkedList instructions = b.Instructions(); Integer index = 0, limit = instructions.size(), nextIndex; for (Iterator it = instructions.iterator(); it.hasNext();) { currentIrInstruction = it.next(); nextIndex = index + 1; next = (nextIndex < limit) ? instructions.get(nextIndex) : null; // System.out.println("Translate: " + inst.Get("global.position") + "::read[" // + inst.Get("reg.dst.load") // + "|" // + inst.Get("reg.p1.load") // + "|" // + inst.Get("reg.p2.load") // + "] >> write[" // + inst.Get("reg.dst.store") // + "|" // + inst.Get("reg.p1.store") // + "|" // + inst.Get("reg.p2.store") // + "]" // + inst.Get("type") // ); // switch (currentIrInstruction.Get("type")) { case "alloc": break; case "label": if (!currentIrInstruction.Get("label").equals(getTarget().Block().getName())) { TranslateLabel(currentIrInstruction); } break; case "assign": TranslateAssign(currentIrInstruction); break; case "unary": TranslateUnary(currentIrInstruction); break; case "copy": TranslateCopy(currentIrInstruction); break; case "jump": TranslateJump(currentIrInstruction); break; case "call": TranslateCall(currentIrInstruction); break; case "return": TranslateReturn(currentIrInstruction); break; case "push_param": TranslatePushParam(currentIrInstruction); break; case "push_return": TranslatePushReturn(currentIrInstruction); break; case "pop_return": TranslatePopReturn(currentIrInstruction); break; case "pop_param": TranslatePopParam(currentIrInstruction); break; case "branch": TranslateBranch(currentIrInstruction); break; case "indexed_assign": TranslateIndexedAssignment(currentIrInstruction); break; case "pointer_assign": TranslatePointerAssignment(currentIrInstruction); break; case "store": TranslateStore(currentIrInstruction); break; case "load": TranslateLoad(currentIrInstruction); break; default: throw new Exception(String.format("TAC instruction type '%s' not defined", currentIrInstruction.Get("type"))); } prev = currentIrInstruction; index++; } } protected Instruction Next() { return next; } protected Instruction Prev() { return prev; } }