package IntermediaryCode; import API.Api; import API.Functions; import API.Types; import API.Utils; import API.Variables; import ast.AbstractSyntaxTree; import ast.Node; import common.Block; import common.Code; import common.DataLayout; import common.Instruction; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import java.util.Stack; import java.util.regex.Pattern; /** * * @author Eugenio */ public final class IRGenerator implements IRGenInterface { protected int jb = 0; protected int incLabel = 0; protected int tmpVarCount = 1; protected boolean inicializado = false; protected boolean enableOtimization = true; protected AbstractSyntaxTree ast; protected Code code; protected Node calEndAtt; protected String label; protected String calEndVar; protected String calEndSize; protected String calEndTipo; protected Pattern ArrayPatternRegex = Pattern.compile(".*\\[.*\\]"); protected Stack master = new Stack<>(); protected ArrayList line = new ArrayList<>(); protected LinkedList branckInvert = new LinkedList<>(); protected HashMap arrayAcesso = new HashMap<>(); protected HashMap varGenMap = new HashMap<>(); protected HashMap funcGenMap = new HashMap<>(); protected HashMap systemCalls = new HashMap<>(); protected ArrayList currentMatrixvalues = new ArrayList<>(); protected HashMap> matrixValues = new HashMap<>(); protected HashMap ArrayShiftMap = new HashMap<>(); protected Stack loopScope = new Stack() { { push(""); } }; protected LinkedHashMap power2 = new LinkedHashMap() { { for (long i = 0; i < 31; i++) { put(Long.toString(Long.valueOf(1 << i)), Long.valueOf(i)); } } }; public static Pattern AddressOperator = Pattern.compile("(\\&|\\*)"); public static Pattern TemporaryAlias = Pattern.compile("_(T|S)"); protected String[] primitives = Types.getPrimitiveTypesList(); public IRGenerator() throws Exception { } public IRGenerator(AbstractSyntaxTree ast) throws Exception { Ast(ast); } protected int calc(ArrayList data) { Integer op1, op2, operacao; switch (data.size()) { case 1: return data.get(0); case 3: op1 = data.remove(0); operacao = data.remove(0); op2 = data.remove(0); if (operacao == 1) { return op1 - op2; // throw new Exception("Quantidade de entradas invalidas!" + data.size()); } else { return op1 + op2; } default: op1 = data.remove(0); operacao = data.remove(0); if (operacao == 1) { return op1 - calc(data); // throw new Exception("Quantidade de entradas invalidas!" + data.size()); } else { return op1 + calc(data); } } } public void Ast(AbstractSyntaxTree ast) throws Exception { this.ast = ast; code = new Code("IR", ast); //Registra o bloco global code.OpenBlock("global"); Block block = code.Block(); // Seta o bloco como bloco de controle block.Type(Block.TYPE_CTRL); // Atribui o contexto do bloco ao contexto global code.GlobalContext(block.Context()); // Encerra o bloco code.CloseBlock(); code.ControlInstructions = "label,alloc".split(","); // Especifica o template engine code.Template(new IRTemplate()); } @Override public Code Create(AbstractSyntaxTree ast) throws Exception { Ast(ast); Code code = run(); // Executa todos os tratametos definidos apos geracao do codigo printVarMap(); code.Print(); return code; } protected Node visit(Node n) throws Exception { if (null == n || n.eq("visited", "true")) { return n; } n.Set("visited", "true"); // System.out.println("Visit:" + n.Class()); switch (n.Class()) { case "dec.const": gerarConstante(n); break; case "if.stmt": IfStmts(n); break; case "selector": Selector(n); break; case "dec.var": // Log.PrintInfo("TAC", new Instruction().Set("msg", "DECVAR." + n)); if (n.find("exprs") != null) { n.Set("class", "dec.var.short").Set("value", "dec.var.short"); genAssign(n); break; } case "def.assign": genAssign(n); break; case "call": genCall(n); break; case "ID": genID(n); break; case "incdec": IncDecStmt(n); break; case "for.stmt": genFor(n); break; case "expr": _visitExpr(n); break; case "unary": unaryStmt(n); break; case "switch.stmt": switchStmt(n); break; case "test": test(n); break; case "return": visitChildrensFirst(n); break; default: visitRootFirst(n); break; } return n; } protected void genID(Node n) throws Exception { // System.out.println("GENID:" + n); n.Set("_return", CreateVar(Variables.Get(n.getText()))); } protected void test(Node n) throws Exception { Node x = null; ArrayList chils = n.childrens(); int size = chils.size(); for (int i = 0; i < size; i++) { x = chils.get(i); visit(x); } n.Copy("_return", x); } protected void IncDecStmt(Node n) throws Exception { Instruction operacao = new Instruction(); String dst = CreateVar(n.findByClass("selector")); operacao.Set("type", "assign") .Set("format", "assign") .Set("cat", "exp") .Set("_return", "exp") .Set("dst", dst) .Set("p1", dst) .Set("p2", "1") .Set("p1value", "" + Api.IsValue(dst)) .Set("p2value", "true") .Set("op", n.findByClass("operator").eq("value", "++") ? "+" : "-"); Add(operacao); } protected void Selector(Node n) throws Exception { String tmp; String shift = null; n.Set("copymode", "copy"); switch (n.Get("subclass")) { case "operand": if (n.eq("classType", "value")) { // n.Set("value", Api.Value(n.getText())); n.Set("_return", Api.Value(n.getText())); } else { String v = CreateVar(n); if (n.eq("pointer", "*") && n.eq("access", "read")) { String t = CreateTmpVar(); Copy(t, v, false); v = t; } n.Set("_return", v); } // System.out.println("Seletor operand:" + n); break; case "index": // shift = n.childrens().Get(0).GetInt("value"); // shift = n.childrens().Get(0).GetInt("value"); shift = ArrayShift(n); case "selector": if (shift == null) { shift = "" + Variables.Shift(n.getText()); } tmp = CreateVar(n) + "[" + shift + "]"; if (!n.eq("access", "write")) { String t = CreateTmpVar(); Copy(t, tmp, false); tmp = t; } n.Set("_return", tmp); break; case "arguments": break; } } protected ArrayList ShiftPath(int size) { ArrayList ret = new ArrayList<>(); FindShiftPath(size, ret); return ret; } protected ArrayList ShiftInterval(int size) { ArrayList ret = new ArrayList<>(); Integer op = 1, i = 1, after, before; // while (true) { after = 1 << (i++); if (after == size) { before = after; break; } else if (after > size) { before = after >> 1; break; } } // before = Math.abs(before - size); // after = Math.abs(after - size); if (Math.abs(before - size) <= Math.abs(after - size)) { // Se o valor anterios for menor que o posterior op = 0; } // else { // // Se o valor posterior for menor que o anterior // } ret.add(before); ret.add(after); ret.add(2, op); // System.out.println("Interval:{" + size + "}" + ret + "::" + op); return ret; } protected void FindShiftPath(int size, ArrayList path) { size = Math.abs(size); ArrayList shift = ShiftInterval(size); int op = shift.get(2), s1 = shift.get(op); // System.out.println("FindShiftPath:(" + power2.containsKey("" + s1) + "|" + size + "|" + s1 + ")\t\t" + shift); // System.out.println(power2); if (power2.containsKey("" + s1)) { path.add(s1); path.add(op); } if (size == 1) { // path.add(size); } // System.out.println("Pathj:" + path); if (path.size() % 2 == 0 && Math.abs(size - s1) == 0) { path.remove(path.size() - 1); return; } FindShiftPath(size - s1, path); // int i = 1, after, before; // while (true) { // after = 1 << (i++); // if (after == size) { // // break; // } else if (after > size) { // break; // } // } // before = after >> 1; // // if (Math.abs(size - before) < Math.abs(after - size)) { // // Se o valor anterios for menor que o posterior // op = 1; // m4 = before; // } else { // // Se o valor posterior for menor que o anterior // op = 0; // m4 = after; // } // FindShiftPath(size, m4, op, path); } protected String ArrayShift(Node n) throws Exception { // Cria a chave para a ocorrencia de um acesso ao array, evitando recalcular o endereco String key = n.getText(); for (Node node : n.childrens()) { // System.out.println("ArrayShift:" + node); key += "_" + node.getText(); } // System.out.println("@@@@@@@@@@ARRAY_SHIFT :" + key); // if (!ArrayShiftMap.containsKey(key)) { // String shift; Node var = Variables.Get(n.getText()); // System.out.println("INDEX shift:" + n + var); for (int i = 0, j = 1; j < var.childrens().size(); j++) { n.childrens().get(i++).Set("collNumber", var.childrens().get(j).getText()); } String ret = CalcArrayAddress(n.childrens(), Types.Size(var.Get("type"))); // Se o offset for calculado em um inteiro atribui o mesmo como shift // if (Utils.IsNumber(ret)) { // shift = ret; // } else { //// Se for um endereci faz a soma com o offset da varivel //// __exp("+", ret, CreateAlias(n), ret); // shift = ret; // } // ArrayShiftMap.put(key, ret); // } //// // return ArrayShiftMap.get(key); return ret; } protected String GenShiftLeftLogical(String var, int size, boolean mps, boolean last) throws Exception { ArrayList path = ShiftPath(size); ArrayList reverse = new ArrayList<>(); for (int i = path.size() - 1; i >= 0; i--) { reverse.add(path.remove(i)); } // System.out.println(">>>>>(var:" + var + ", size:" + size + ") arithpath:" + reverse); var = GSLL(var, reverse, mps, size, last); return var; } protected long pow2(long p) { return pow2("" + p); } protected long pow2(String p) { return power2.get(p); } protected String GSLL(String var, ArrayList path, boolean mps, int size, boolean last) throws Exception { int op1, operacao, op2; // String T1 = CreateTmpVar(), String T1 = var, T2 = CreateTmpVar(); // T3 = CreateTmpVar(); switch (path.size()) { case 1: if (!mps) { // Copy(T1, var, false) // .Set("comment", "Copy value of index M1") // .Set("copy", "true"); } else { T1 = var; } if (!last) { // System.out.println("GSLL:" + size + ":" + pow2(size)); __exp("<<", T1, "" + pow2(size), T2); return T2; } return T1; case 3: op1 = path.remove(0); operacao = path.remove(0); op2 = path.remove(0); // String T4 = CreateTmpVar(); if (!mps) { Copy(T1, var, false) .Set("comment", "Copy value of index M3") .Set("copy", "true"); } if (op1 != 1) { __exp("<<", T1, "" + pow2(op1), T1); } // if (op2 == 1) { // } else { // Copy(T3, var, false).Set("comment", "Copy value of index"); if (op2 != 1) { __exp("<<", T1, "" + (pow2(op2) - pow2(op1)), T2); // deve realizar um novo deslocamento } else { T2 = T1; } // Soma o deslocamento com o tamanho __exp("+", T1, T2, T1).Set("comment", ""); return T1; default: // op1 = path.remove(0); // operacao = path.remove(0); // // T2 = GSLL(var, path); // // Copy(T1, var, false).Set("comment", "Copy value of index"); // // __exp("<<", T1, "" + pow2(op1), T1).Set("comment", ""); // __exp("+", T1, T2, T1).Set("comment", ""); } return var; } protected String CalcArrayAddress(ArrayList childrens, int Size) throws Exception { // System.out.println("CalcArrayAddressINIT(" + Size + "):"); boolean onlyNumber = true; for (Node node : childrens) { if (!node.isNumber("value")) { onlyNumber = false; break; } } if (onlyNumber) { return "" + (CalcArrayAddressNumber(childrens, Size) * Size); } else { // System.out.println("CAA:" + childrens); String current = CalcArrayAddressAux(childrens, Size); // System.out.println("Size {" + current + "}:----------->" + Size); // multiplica pelo tamanho return GenShiftLeftLogical(current, Size, true, false); } } protected Integer CalcArrayAddressNumber(ArrayList childrens, int Size) throws Exception { Node ind; ind = childrens.remove(0); Integer value = ind.GetInt("value"); // ultimo elemento da idexacao if (childrens.size() == 0) { return value; } Integer collNumber = ind.GetInt("collNumber"), ret = CalcArrayAddressNumber(childrens, Size); return ((value * collNumber) + ret); } protected String CalcArrayAddressAux(ArrayList childrens, int Size) throws Exception { // boolean multPerSize = true; int collNumber; Node ind, nextIndex; ind = childrens.remove(0); // System.out.println("CalcArrayAddressAux:" + childrens.size() + ":" + Size + "\n" + ind); String current, varname; if (ind.eq("class", "expr")) { varname = CreateTmpVar(); Node p1 = visit(ind.childrens().get(0)), p2 = visit(ind.childrens().get(1)); __exp(ind.getText(), p1.Get("_return"), p2.Get("_return"), varname); } else { varname = CreateVar(ind); } // if (ind) // ultimo elemento da idexacao if (childrens.size() == 0) { if (Utils.IsNumber(ind.getText())) { return "" + ind.GetInt("value"); } else { return GenShiftLeftLogical(varname, Size, false, true); } } collNumber = ind.GetInt("collNumber"); nextIndex = childrens.get(0); if (ind.isNumber("value") && nextIndex.isNumber("value")) { // System.out.println("CalcArray:" + ind.GetInt("value") + ":" + ind.GetInt("collNumber") + ":" + Integer.parseInt(ret)); current = "" + (ind.GetInt("value") * collNumber); } else { current = GenShiftLeftLogical(varname, collNumber, false, false); } String ret = CalcArrayAddressAux(childrens, Size); __exp("+u", current, ret, current).Set("comment", "colls shift"); return current; } /** * ProceSSa um node:
* Ordem:
* ->Primeiro filhoS;
* ->No principal;
* * @param n * @throws Exception */ protected void visitChildrensFirst(Node n) throws Exception { // System.out.println("Visit:" + n.getText()); for (Node n1 : n.childrens()) { // System.out.println("Visit:" + n1.getText()); visit(n1); } // System.out.println("Process:" + n.getText()); processarNode(n); } /** * ProceSSa um node:
* Ordem:
* ->Primeiro filho;
* ->No principal;
* ->Segundo filho;
* * @param n * @throws Exception */ protected void visitNoMeio(Node n) throws Exception { visit(n.getFilho(0)); processarNode(n); visit(n.getFilho(1)); } /** * ProceSSa um node:
* Ordem:
* ->No princial;
* ->DepoiS oS filhoS * * @param n * @throws Exception */ protected void visitRootFirst(Node n) throws Exception { processarNode(n); for (Node n1 : n.childrens()) { visit(n1); } } /** * Aloca endereço no inicio da memoria para conStanteS ApenaS tipoS
* [inteiro, booleano e char] * * @param n * @throws Exception */ protected void gerarConstante(Node n) throws Exception { // System.out.println("Gerando constant:" + n.childrens().Get(0) + n.childrens().Get(1)); // CreateAlias(n.Get(label, label)); // getLabel("C", n); // if (n.closest("block", "class") != null) { // code.registerVar(n.Get("_return"), 1, DataLayout.TYPE_VAR); // } } /** * Executa a extração fo block principal * * @throws Exception */ public boolean main() throws Exception { Node main = ast.getMain(); if (main != null) { // main.Set("_return", Threads.getId("main")); Node stmts = main.find("stmts"); if (stmts.childrens().size() > 0 && code.OpenBlock("main")) { // basicBlock.push("main"); // basicBlockCount.push(0); PushLabel("main", "block"); visit(stmts); PushLabel("main-end", "block"); // basicBlock.pop(); // basicBlockCount.pop(); code.CloseBlock(); return true; } } return false; } public Code run() throws Exception { if (!inicializado) { inicializado = true; if (!main()) { //Se a função main não possui statments gera o codigo para as outras funcoes ArrayList functions = ast.getRoot().findAll("dec.func", "class", 0); for (Node n : functions) { // System.out.println("Gen Func:" + funcGenMap + n); // genFunction("main." + n.getText(), n); genFunction(n.getText(), n); } } } // Atualiza as posivos de todas as instruções e labels code.UpdatePositions(); return code; } // Atualiza as posivos de todas as instruções e labels protected void UpdatePositions() { Block b; // Reseta a posicao inicial; code.PosicaoLabel = 0; for (Map.Entry x : code.Blocks().entrySet()) { b = x.getValue(); b.CurrentAddress = 0; for (Instruction n : b.Instructions()) { // System.out.println("Update->:" + CurrentAddress + ":" + code.Position()); switch (n.Get("type")) { case "label": n.Set("reference.position", b.CurrentAddress) .Set("global.reference.position", code.Position()); code.RegisterLabelAddress(n.Get("label")); case "alloc": break; default: n.Set("block.position", b.CurrentAddress) .Set("block.position.origin", b.CurrentAddress++) .Set("global.position", code.PositionInc()); } } } } /** * ProceSSa If (ElSe'Set)* * * @param n * @throws Exception */ protected void IfStmts(Node n) throws Exception { String end = gerarLabel(), next; int size = n.childrens().size(), last = size - 1, current = 0; boolean ifChain = size > 1; //(If)+ (else)? next = ifChain ? gerarLabel() : end; n.Set("next", next).Set("end", end); for (Node stmt : n.childrens()) { switch (stmt.Class()) { case "if.case.stmt": IfCaseStmt(n, stmt, ifChain, (current == last)); current++; break; // Else case case "stmts": // String next = gerarLabel(); // n.Set("next", next); visit(stmt.Set("next", next)); // Cria um PushLabel final // PushLabel(n.Get("end"), "branch"); // PushLabel(end); break; } } // Cria um PushLabel final // System.out.println("Label end:" + n.Get("end")); PushLabel(n.Get("end"), "branch"); } /** * ProceSSa If, eSSe metodo deve Ser chamado pelo metodo IfStmtS * * @param n * @param _if * @param ifChain * @throws Exception */ protected void IfCaseStmt(Node n, Node _if, boolean ifChain, boolean last) throws Exception { Node test = _if.first(); String testType = "jb"; if (test.childrens().size() > 1) { visit(test.childrens().get(0)); test = test.last(); } else { test = test.first(); } Node stmts = _if.find("stmts"); // Se o teste falha deve saltar o bloco n.Set("start", gerarLabel()); test.Set("test.type", testType).Copy("next,start,end", n); Branch(test, 0); // marca com um label o inicio do bloco do if PushLabel(n.Get("start"), "branch"); // gera as instruções do bloco visit(stmts); // se for uma cadeia de condiçoes com ou sem else if (ifChain) { if (!last) { // Salta os outros testes _goto(n.Get("end")); } //Adiciona o label de proximo elemento da cadeia de if's e else PushLabel(n.Get("next"), "branch"); //Atualiza o ponteiro para o proximo elemento n.Set("next", gerarLabel()); } } /** * Executa tratamento de um no eSpecifico, Selecionado pelo atributo claSS * * @param n * @throws Exception */ protected void processarNode(Node n) throws Exception { switch (n.Class()) { case "return": genReturn(n); break; case "ctrl.stmt": ctrlStmt(n); break; case "label.stmt": PushLabel(n.getText(), "user"); break; } } protected void _visitExpr(Node n) throws Exception { visit(n.childrens().get(0)); visit(n.childrens().get(1)); // System.out.println("VisitExpr:" + n); switch (n.Get("subclass")) { case "arith":// ( + | - | * | / ) integer genExpArith(n); break; } } protected void BranchAnd(Node n, int index) throws Exception { // int pos = 0; // if (n.parent == null) { // System.out.println("BranchAnd:" + n); // } // OrTestAndOccurrence++; Instruction instruction = null; ArrayList x = n.childrens(); Node op1 = x.get(0), op2 = x.get(1); String type = n.Get("test.type"), step = gerarLabel(), attrs = "next,end,inc,test.type,skip.test"; n.Set("skip.test", step); op1.Copy(attrs, n); op2.Copy(attrs, n); instruction = Branch(op1, 1); if (instruction != null) { switch (type) { case "jtb": instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); if (n.parent != null && n.parent.eq("value", "||")) { if (index == 1) { UpdateLabel(instruction, n.parent.Get("skip.test")); } else if (index == 2) { UpdateLabel(instruction, n.parent.Get("end")); } // } else if (n.parent.eq("value", "&&")) { } else { UpdateLabel(instruction, n.Get("end")); } break; case "jb": // if (n.parent != null) { if (n.parent != null && n.parent.eq("value", "||")) { if (index <= 1) { UpdateLabel(instruction, n.parent.Get("skip.test")); } else if (index == 2) { // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("next")); } } // } else { // } } } // System.out.println("instruction Branch 1:" + instruction + "\n" + op1); // if (index == 0 || (op1.in("value", new String[]{"||", "&&"}) && !n.eq("value", op1.Get("value")))) { // Registra o label para o saldo dos testes do primeiro parametro PushLabel(step, "branch"); // } instruction = Branch(op2, 2); if (instruction != null) { switch (type) { case "jtb": if (n.parent != null && n.parent.eq("value", "||")) { if (index == 1) { // teste 1 do parametro 2 com pai || instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("end")); } else if (index == 2) { // teste 2 do parametro 2 UpdateLabel(instruction, n.Get("next")); } // } else if (n.parent.eq("value", "&&")) { // if (index == 1) { // teste 1 do parametro 2 com pai && //// throw new Exception("// teste 1 do parametro 2 com pai &&"); // // } else if (index == 2) { // teste 2 do parametro 2 com pai && // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); // UpdateLabel(instruction, n.Get("end")); // } } else { if (index == 1) { // teste 1 do parametro 2 geral instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("end")); } else if (index == 2) { // throw new Exception("teste 2 do parametro 2 geral"); } } break; case "jb": // System.out.println("I(jb:and:2)[" + index + "]\n" + instruction + "\n" + n); // if (n.parent != null) { if (n.parent != null && n.parent.eq("value", "||")) { if (index <= 1) { // UpdateLabel(instruction, n.parent.Get("skip.test")); instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("start")); } else if (index == 2) { // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("next")); } } // } else { // }// } else { // } } } } public void UpdateLabel(Instruction I, String label) { String copy = I.Get("label"); if (!copy.equals("")) { code.RemoveLabelReference(copy); } I.Set("label", label); code.AddLabelReference(label); } protected void BranchOr(Node n, int index) throws Exception { // if (n.parent == null) { // System.out.println("BranchOr:" + n); // } // int pos = 0; // OrTestAndOccurrence++; Instruction instruction = null; ArrayList x = n.childrens(); Node op1 = x.get(0), op2 = x.get(1); String type = n.Get("test.type"), step = gerarLabel(), attrs = "next,start,end,inc,test.type,skip.test"; n.Set("skip.test", step); op1.Copy(attrs, n); op2.Copy(attrs, n); // System.out.println("BranchOr:" + n.parent); // Executa o lado esquerdo do || instruction = Branch(op1, 1); if (instruction != null) { switch (type) { case "jtb": if (n.parent != null && n.parent.eq("value", "&&")) { if (index == 1) { UpdateLabel(instruction, n.parent.Get("skip.test")); } } break; case "jb": // System.out.println("I(jb:1)[" + index + "]\n" + instruction + "\n" + n); // System.out.println("Entrei no jb ||" + (jb++) + instruction + n.parent); // if (n.parent != null) { if (n.parent != null && n.parent.eq("value", "||")) { // if (index == 2) { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("start")); // } } else if (n.parent != null && n.parent.eq("value", "&&")) { if (index <= 1) { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.parent.Get("skip.test")); } else if (index == 2) { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.parent.Get("start")); } // } } else { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); if (index <= 1) { UpdateLabel(instruction, n.Get("start")); } else if (index == 2) { } } } } // System.out.println("instruction Branch 1:" + instruction + "\n" + op1); // Registra o label para o saldo dos testes do primeiro parametro PushLabel(step, "branch"); // Executa o lado direito do || instruction = Branch(op2, 2); if (instruction != null) { switch (type) { case "jtb": if (n.parent != null && n.parent.eq("value", "&&")) { if (index == 1) { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.parent.Get("end")); } } break; case "jb": // if (n.parent != null) { if (n.parent != null && n.parent.eq("value", "||")) { if (index <= 1) { instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("start")); } else if (index == 2) { // // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); UpdateLabel(instruction, n.Get("next")); } } else if (n.parent != null && n.parent.eq("value", "&&")) { if (index == 1) { // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); // UpdateLabel(instruction, n.parent.Get("start")); } else if (index == 2) { // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); // UpdateLabel(instruction, n.parent.Get("start")); } // } } else { // instruction.Set("op", Utils.ComplementOperation(instruction.Get("op"))); // UpdateLabel(instruction, n.Get("next")); } } } } protected Instruction BranchTest(Node n, int index) throws Exception { ArrayList x = n.childrens(); String type = n.Get("test.type"); boolean invert = false; String op, p0, p1; switch (type) { case "jb": invert = true; break; case "jtb": break; default: throw new Exception("test.type '".concat(type).concat("' not suported. Values {jtb,jb}")); } visit(n); // Resultado do test class ou acesso a um id ou bool if (!n.eq("class", "expr")) { op = "=="; p0 = n.Get("_return"); p1 = "1"; } else { //(<, <=, >, >=, ==, !=) op = n.getText(); p0 = visit(x.get(0)).Get("_return"); p1 = visit(x.get(1)).Get("_return"); } // Inverte o teste e salta o bloco if (invert) { op = Utils.ComplementOperation(op); } // return Branch(op, p0, p1, next); Instruction r1 = new Instruction().Set("label", n.Get("next")); Boolean p0IsValue = Api.IsValue(p0), p1IsValue = Api.IsValue(p1); if (p0IsValue && p1IsValue) { // Se a expressão for resolvivel e o resultado é positivo // A instrução de saldo é adicionada if (Utils.ResolveExprBool(op, p0, p1)) { Add(r1.Set("type", "jump").Set("format", "jump")); } } else { Add(r1.Set("format", "branch") .Set("type", "branch") .Set("op", op) .Set("p1", p0) .Set("p2", p1) .Set("p1value", "" + p0IsValue) .Set("p2value", "" + Api.IsValue(p1))); } // System.out.println("Add branch:" + branckInvert.peek() + branckInvert + ">>" + (!branckInvert.isEmpty() && branckInvert.peek()) + "\n" + r1); return r1; } protected Instruction Store(String addr, String src) throws Exception { Instruction add = Add(new Instruction() .Set("type", "store") .Set("format", "store") .Set("dst", blockVarAliasCtx.peek().Reverse(addr)) .Set("p1", src)); if (!addr.equals(src)) { // System.out.println("Store:" + addr + ":" + src); blockVarAliasCtx.peek().SetLoaded(addr, false); } return add; } protected Instruction Load(String attr, String dst) throws Exception { blockVarAliasCtx.peek().SetLoaded(attr); return Add(new Instruction() .Set("type", "load") .Set("format", "load") .Set("dst", dst) .Set("p1", blockVarAliasCtx.peek().Reverse(attr))); } protected Instruction Branch(Node n, int index) throws Exception { Instruction instruction = null; switch (n.getText()) { case "&&": BranchAnd(n, index); break; case "||": BranchOr(n, index); break; default: instruction = BranchTest(n, index); } return instruction; } /** * Cria uma linha de Salto para PuShLabel eSpecificado no parametro. * * @param label * @throws Exception */ protected void _goto(String label) throws Exception { Instruction r = new Instruction(); r.Set("label", label) .Set("type", "jump") .Set("format", "jump") .Set("locker", getIdMaster()); Add(r); } /*Inicio das avaliacoes booleanas*/ /** * Gera um linha de inStrução de retorno no block de codigo * * @param n * @throws Exception */ protected void genReturn(Node n) throws Exception { Instruction nreg; ArrayList returns = n.find("exprs").childrens(); for (Node ret : returns) { // System.out.println("Return p:" + ret); nreg = new Instruction() .Set("type", "push_return") .Set("format", "push_return") .Set("p1value", "" + Api.IsValue(ret.getText())) .Set("p1", ret.Get("_return")); nreg.Set("locker", getIdMaster()); Add(nreg); } Add(new Instruction() .Set("type", "return") .Set("format", "return") .Set("p1", returns.size()) .Set("p1value", "true") .Set("locker", getIdMaster())); } /** * Gera todoS oS SaltoS de um loop for * * @param n * @throws Exception */ protected void genFor(Node n) throws Exception { String attrs = "next,end,inc,test"; loopScope.push(n.Get("scope")); setMaster(n); String next = gerarLabel(), // next = gerarLabel(), end = gerarLabel(), inc = gerarLabel(), testLabel = gerarLabel(); n.Set("next", next) .Set("end", end) .Set("inc", inc) .Set("test", testLabel); Node stmt = n.find("stmts"); stmt.Copy(attrs, n); boolean hasTest = false; Node t = n.find("test"), test = null; if (t.childrens().size() > 0) { hasTest = true; test = t.first(); test.Copy(attrs, n).Set("test.type", "jtb"); } /*Inicializacoes e atribuicoes*/ visit(n.find("initialization")); if (hasTest) { /*Salta para o teste do laco*/ _goto(testLabel); } /*Marca o inicio do bloco do laco*/ PushLabel(next, "branch"); /*Executa o bloco do for*/ visit(stmt); /*Label que marca os incrementos dos laco*/ if (code.CountReferenceLabel(inc) > 0) { PushLabel(inc, "branch"); } /*Executa os incrementos*/ visit(n.find("increment")); // test.type = ((JumpToBlock in LOOP) | (JumpBlock in IF || SWITCH)) // test.type = JumpToBlock // test.Set("test.type", "for").Set("next", next).Set("end", end).Set("or", next); // System.out.println("Teste:" + test); if (hasTest) { /*Label que marca o teste do laco*/ PushLabel(testLabel, "branch"); Branch(test, 0); } else { _goto(next); } if (code.CountReferenceLabel(end) > 0) { PushLabel(end, "branch"); } setNullMaster(); loopScope.pop(); } // protected void genFor(Node n) throws Exception { // setMaster(n); // String start = gerarLabel(), next = gerarLabel(); // // n.Set("next", next); // n.Set("start", start); // // Node stmt = n.find("stmts"); // stmt.Set("next", start); // /*Inicializacoes e atribuicoes*/ // visit(n.find("initialization")); // // Label que marca o inicio do for // PushLabel(start, "branch"); // // Node test = n.find("test").first(); //// if (test.hasChildrens()) //// test.Set("true", gerarLabel()); //// test.Set("false", n.Get("next")); //// test.Set("true", next); //// test.Set("false", n.Get("next")); // test.Set("and", next); // test.Set("next", next); // test.Set("or", gerarLabel()); // // Branch(test); // // if (test.Has("or")) { // PushLabel(test.Get("or"), "branch"); // } // //// PushLabel(test.Get("true"), "branch"); // /*Executa o bloco do for*/ // visit(stmt); // /*Executa os incrementos*/ // visit(n.find("increment")); // /*Salta para inicio do laço*/ // _goto(start); // /*Marca o endereço final para sair do laço*/ // PushLabel(test.Get("next"), "branch"); // // setNullMaster(); // } protected void genExpArith(Node n) throws Exception { Node op1 = n.childrens.get(0); Node op2 = n.childrens.get(1); String _op = n.getText(); // System.out.println("Gen genExpArith:" + _op); // // // // se os dois valores são // if (op1.eq("type", "value") && op2.eq("type", "value")) { // // n.Set("_return", resolveExpr(_op, op1.Get("value"), op2.Get("value"))); // } // if (op1.IsNumber("value") && op2.IsNumber("value")) { // // } else { // Inverte a ordem dos operandos se o segundo for seletor e o primeiro for valor if (op1.isNumber("value") && !op2.isNumber("value")) { Node aux = op1; op1 = op2; op2 = aux; } // System.out.println("GerarArit" + op1 + "-" + op2); String _p1 = op1.Get("_return"); String _p2 = op2.Get("_return"); String _return = CreateTmpVar(); n.Set("_return", _return); Instruction instruction = __exp(_op, _p1, _p2, _return); if (instruction.eq("type", "copy")) { n.Set("_p1", instruction.Get("p1")).Set("value", instruction.Get("p1")); } else { n.Set("_op", _op).Set("_p1", _p1).Set("_p2", _p2); } } /** * Para cima verificado <==> */ protected void genArray(Node n) { if (n.eq("raiz", "t")) { currentMatrixvalues = new ArrayList(); matrixValues.put(n.Get("id"), currentMatrixvalues); for (Node c : n.childrens()) { genArray(c); } } else if (n.eq("terminal", "t")) { currentMatrixvalues.add(n.getText()); } else { for (Node c : n.childrens()) { genArray(c); } } } protected ArrayList initValues(Node n) { ArrayList values = new ArrayList<>(); switch (n.Get("class")) { case "_array": values = matrixValues.get(n.Get("id")); break; /*valores e constantes*/ default: String _return = n.Get("_return"); if (_return.matches("^_.*")) { _return = "0"; } values.add(_return); } return values; } /** * Gera a chamada para o metodo de deSalocacao de memoria * * @param n * @throws Exception */ protected void genDelete(Node n) throws Exception { for (Node address : n.childrens()) { visit(address); __genParam(address.Get("_return")); __gerarCall(Functions.FREE, "1", getIdMaster()); } } /** * Gera a Switch caSe * * @param n */ protected void switchStmt(Node n) throws Exception { /*Label que sera consultado pelo break para sair do case*/ String start, next, end = gerarLabel(), dst = null; n.Set("next", end); Node test = n.find("test"); // Verifica se existe entrada para selecao if (test.childrens().size() > 0) { test = test.first(); visit(test); dst = test.Get("_return"); } // test; ArrayList cases = n.findAll("def.case", "class", 1); int current = 0, last = cases.size() - 1; for (Node _case : cases) { start = gerarLabel(); next = gerarLabel(); _case.Set("start", start) .Set("_input", dst) .Set("next", next) .Set("end", end) .Set("test.type", "jb"); genCase(_case, current == last); current++; } /*Marca o endereço final para sair do switch*/ PushLabel(end, "branch"); } /** * Gera oS caSeS de um Switch * * @param n */ protected void genCase(Node n, Boolean last) throws Exception { ArrayList exprs; Node test; // System.out.println("GEN_CASE:" + n); // String start = n.Has("start") ? n.Get("start") : gerarLabel(); // String next = gerarLabel(), end; // //// System.out.println("GenCase:" + start + ":" + next); ArrayList itens = n.childrens(); Node stmts = n.find("stmts"); // Node or; // if (itens.size() >= 2) { // Tem teste test = n.first(); String input = n.Get("_input"), start = n.Get("start"), end = n.Get("end"), next = n.Get("next"); // if (input != null) { exprs = ExprsEq(test, new Node(input).Set("_return", input)); } else { exprs = test.childrens(); } // // Atualiza o PushLabel de sucesso das exprs for (Node expr : exprs) { expr.Copy("start,next,end,test.type", n); } // Branch(OR(exprs).Set("next", next), 0); /*Se nenhum dos casos for compativel salta para o proximo*/ /*Marca o PushLabel inicial do caso*/ PushLabel(start, "branch"); /*Visita o bloco do case*/ visit(stmts); // System.out.println("Gen case :" + last); if (!last) { /*Salta para o proximo case ou para o fim do switchcase*/ _goto(end); } /*Label do inicio do proximo case*/ PushLabel(next, "branch"); } else { // Default statiment visit(stmts); } // String start = n.Has("start") ? n.Get("start") : gerarLabel(); // String next = gerarLabel(), end; // //// System.out.println("GenCase:" + start + ":" + next); // ArrayList itens = n.childrens(); // Node stmts = n.find("stmts"); // Node or; // // if (itens.size() >= 2) { // Tem teste // String input = n.Get("_input"); // Node test = n.first(); // ArrayList exprs; // // if (input != null) { // exprs = ExprsEq(test, new Node(input).Set("_return", input)); // } else { // exprs = test.childrens(); // } // // /*Seleciona o endereco de saida se é no proximo case ou no fim do switch*/ // if (stmts.last().eq("value", "fallthrough")) { // end = gerarLabel(); // n.Set("next", end); // } else { // end = n.Get("end"); // } // // // Atualiza o PushLabel de sucesso das exprs // for (Node expr : exprs) { // expr.Set("true", !last ? next : end); //// expr.Set("false", next); //// expr.Set("false", start); // } // // Branch(OR(exprs).Set("next", next), 0); // // /*Se nenhum dos casos for compativel salta para o proximo*/ //// _goto(!last ? next : end); // /*Marca o PushLabel inicial do caso*/ // PushLabel(start, "branch"); // /*Visita o bloco do case*/ // visit(stmts); // // if (!last) { // /*Salta para o proximo case ou para o fim do switchcase*/ // _goto(end); // /*Label do inicio do proximo case*/ // PushLabel(next, "branch"); // } // } else { // Default statiment // visit(stmts); // } } protected Node NodeBoolExpr(String op, Node e1, Node e2) { return new Node(op) .Set("type", "bool") .Set("class", "expr") .Set("subclass", "bool") .addFilho(e1) .addFilho(e2); } protected ArrayList ExprsEq(Node n, Node input) throws Exception { ArrayList list = new ArrayList<>(); switch (n.Class()) { case "exprs": for (Node e : n.childrens()) { list.add(NodeBoolExpr("==", input, e)); } break; default: list.add(NodeBoolExpr("==", input, n)); } return list; } protected Node OR(ArrayList n) throws Exception { switch (n.size()) { case 0: return null; case 1: return n.get(0); default: Node x = n.get(0); n.remove(x); return NodeBoolExpr("||", x, OR(n)).Copy("start,next,end,test.type", x); } } protected int qtdByIndex(Node n) throws Exception { Node indexes = n.find("indexes"); if (indexes == null) { return 1; } else { int sum = 0; for (Node index : indexes.childrens()) { sum += index.GetInt("_return"); } return sum; } } /** * Gera inStrução de atribuicao * * @param n * @throws Exception */ protected void genAssign(Node n) throws Exception { // System.out.println("GENAssign :" + n); ArrayList localExpr = new ArrayList<>(); ArrayList localAttribs = new ArrayList<>(), // copymode = new ArrayList<>(), // operators = new ArrayList<>(), returns; ArrayList copyaddress = new ArrayList<>(); String p1, modify = n.Get("modify"), declare = "" + n.getText().equals("dec.var.short"); // System.out.println("genAssign:" + n.childrens().Get(0).childrens().Get(0)); Node dsts = n.childrens().get(0); if (n.in("value", new String[]{"dec.var.short", "def.assign"})) { for (Node attrib : n.childrens().get(1).childrens()) { // System.out.println(">n:" + attrib); visit(attrib); // System.out.println("n:" + attrib); // System.out.println("genAssign:" + attrib.Get("class") + ":" + attrib.Get("value")); if (attrib.eq("class", "call")) { returns = attrib.getList("returns"); if (returns != null) { for (String _return : returns) { localAttribs.add(_return); copyaddress.add(attrib.eq("subclass", "address")); } } } else if (attrib.eq("class", "index")) { // System.out.println("Attr <- :" + attrib); } else if (attrib.eq("class", "literal")) { // System.out.println("literal<- :" + attrib); switch (attrib.Get("subclass")) { case "array": for (Node element : attrib.find("exprs").childrens()) { visit(element); copyaddress.add(element.eq("subclass", "address")); localAttribs.add(element.Get("_return")); } break; } } else { // System.out.println("Assign:" + attrib); copyaddress.add(attrib.eq("subclass", "address")); localAttribs.add(attrib.Get("_return")); } localExpr.add(attrib); } } // System.out.println("Copy::" + localAttribs); // System.out.println("Lista de atribuicoes locais:\n" + dsts + "\n>>\n" + n); // System.out.println("Lista de atribuicoes locais:\n" + dsts + "\n>>\n" + localAttribs); Node attrib; // Executa a copia dos valores for (int dstPosition = 0, i = 0; i < localAttribs.size(); dstPosition++) { Node d = dsts.childrens().get(dstPosition); d.Set("declare", declare); visit(d); // System.out.println("D:" + d); if (d.eq("class", "unary") && d.eq("dst.pointer", "*")) { p1 = localAttribs.get(i); Add(new Instruction() .Set("format", "pointer_assign") .Set("type", "pointer_assign") .Set("dst", d.childrens().get(1).Get("_return")) .Set("p1", p1) .Set("p1value", "" + Api.IsValue(p1)) .Set("dst.pointer", "*") .Set("locker", getIdMaster())); i++; // Salva o valor em memoria } else if (d.eq("array", "true")) { for (int j = 0; j < d.GetInt("array_size"); j++, i++) { // System.out.println("ARRAY:" + d.Get("_return") + "[" + j + "]" + " -- " + localAttribs.Get(i)); // Copy(d.Get("_return") + "[" + j + "]", localAttribs.get(i), copyaddress.get(i)); Store( d.Get("_return") + "[" + j + "]", localAttribs.get(i) ); } } else { // Copia valor para endereco // System.out.println("Attrib[" + modify + ":" + (modify.equals("")) + "]:" + d.Get("_return") + "<" + localAttribs.Get(i)); if (!modify.equals("")) { __exp(modify, d.Get("_return"), localAttribs.get(i), d.Get("_return")).Set("comment", ""); } else { attrib = localExpr.get(i); //// if (attrib.eq("class", "expr")) { ////// System.out.println("Attrib:" + attrib); //// __exp(attrib.Get("_op"), attrib.Get("_p1"), attrib.Get("_p2"), d.Get("_return")).Set("comment", ""); //// } else { // Copy(d.Get("_return"), localAttribs.get(i), copyaddress.get(i)); //// } // System.out.println("blockVarAliasCtx.peek(" + d.Get("_return") + "):" + blockVarAliasCtx.peek().Reverse(d.Get("_return"))); Store( d.Get("_return"), localAttribs.get(i) ); } i++; } } } protected void __genParam(String param) throws Exception { Instruction r = new Instruction(); r.Set("format", "push_param") .Set("type", "push_param") .Set("p1", param) .Set("p1value", "" + Api.IsValue(param)) .Set("locker", getIdMaster()); Add(r); } protected void genFunction(String id, Node func) throws Exception { if (!funcGenMap.containsKey(id)) { funcGenMap.put(id, "true"); // Empilha um novo contexto de variaveis blockVarAliasCtx.add(new BlockVarMap()); Node block = func.find("stmts"); // basicBlock.push(id); // basicBlockCount.push(0); code.OpenBlock(id); /*Cria a PushLabel inicial da funcao*/ PushLabel(id, "block"); /*Declara as variaveis de parametro*/ genPopParams(func); /*Declara as variaveis de retorno caso sejam nomeadas*/ // visit(func.find("def::return")); // System.out.println(Variables.printScope(func.Get("scope"))); /*Processa o bloco de instrucoes*/ visit(block); /*Cria a PushLabel final da funcao*/ PushLabel(id + "-end", "block"); code.CloseBlock(); //Desempilha o contexto de variaveis para a funcao anteriro blockVarAliasCtx.pop(); // basicBlock.pop(); // basicBlockCount.pop(); } } protected void genCall(Node n) throws Exception { int argsNum = 0; // Se for metodo carrega o contexto no primeiro parametro // System.out.println("GenCall:" + n); if (!n.eq("ctx", "")) { Node var = Variables.Get(n.Get("ctx")); // System.out.println(""); // __genParam("&" + CreateAlias(var)); // Add(new Instruction() // .Set("", PushLabel)); // CreateAlias(var) __genParam(CreateVar(var)); argsNum++; } // Gera os argumentos Node args = n.find("arguments").find("exprs"); if (args != null) { for (Node param : args.childrens()) { // Processa o argumento para obter o _return visit(param); // Cria a instrução de parametro __genParam(param.Get("_return")); } argsNum += args.getChildrenCount(); } // System.out.println("GetMETHOD" + n.getText()); Node def = Functions.Get(n.getText()); String id = def.getText(); // System.out.println("GenCall:" + id + "\n" + def); genFunction(id, def); code.Block().AddDependence(id); // Cria a instrução de chamada Instruction r = __gerarCall(id, "" + argsNum, getIdMaster(), def.find("dec.return")); // System.out.println("CALL -> " + r.getList("returns")); n.addList("returns", r.getList("returns")); } protected String UnaryResolve(String op, String value) throws Exception { switch (op) { case "-": return "-" + value; case "!": return "" + (value.equalsIgnoreCase("false") || value.equals("0") ? "1" : "0"); } throw new Exception(String.format("Invalid [%s]%s ", op, value)); } /*Fim dos laços*/ /*Inicio das operacoes aritimeticas*/ /** * Unary pode Ser uma expreSSão do tipo
* (&|*)addreSS - operacao de ponteiroS
* (-) addreSS|value - negação aritimetica
* (!) addreSS|value - negação booleana * * @param n * @throws Exception */ protected void unaryStmt(Node n) throws Exception { String op = n.childrens().get(0).getText().trim(); Node value = n.childrens().get(1); visit(value); String _ret, _val = value.Get("_return"); // Se for escrita verifica se é escrita no ponteir ou no lugar referenciado if (Api.IsValue(_val)) { _ret = UnaryResolve(op, _val); // } else { } else if (n.eq("access", "write")) { _ret = "ERR"; n.Set("dst.pointer", op); } else { // System.out.println("N:[" + n.Get("id") + "]"); _ret = CreateTmpVar(); // System.out.println("Unary:" + n.childrens().Get(1)); String type; if (AddressOperator.matcher(op).matches()) { type = "pointer_assign"; } else { type = "unary"; } Instruction r = new Instruction() .Set("type", type) .Set("format", type) .Set("dst", _ret) .Set("p1", _val) .Set("op", op) .Set("copymode", "unary") .Set("p1value", "" + Api.IsValue(_val)) .Set("locker", getIdMaster()); Add(r); // System.out.println("N:" + n); // throw new Exception("Unary Stmt not defined"); } n.Set("_return", _ret); // System.out.println("UnaryStmt:[" + _val + ":" + op + "]" + n); } protected Instruction __exp(String op, String p1, String p2, String ret) throws Exception { boolean p1value = Api.IsValue(p1), p2value = Api.IsValue(p2); String unsigned = "false"; if (op.contains("u")) { op = op.replace("u", ""); unsigned = "true"; } Instruction r = new Instruction(); if (p1value && p2value) { r.Set("type", "copy") .Set("format", "copy") .Set("p1value", "true") .Set("p1", "" + Utils.ResolveExpr(op, p1, p2)); } else { r.Set("type", "assign") .Set("format", "assign") .Set("cat", "exp") .Set("p1", p1) .Set("p2", p2) .Set("copymode", "assign") .Set("p1value", "" + p1value) .Set("p2value", "" + p2value); // System.out.println("__EXP:" + r); } r.Set("dst", ret) .Set("op", op) .Set("op.unsigned", unsigned) .Set("locker", getIdMaster()); return Add(r); } /** * Gera Salto para inStruçõeS de continue e break; * * @param n * @throws Exception */ protected void ctrlStmt(Node n) throws Exception { String go; Node ctn = n.closest("for.stmt,switch.stmt", "class"); switch (n.getText()) { case "continue": go = ctn.Get(ctn.eq("class", "for.stmt") ? "inc" : "end"); break; case "break": go = ctn.Get("end"); break; case "goto": go = n.Get("label"); break; default: throw new Exception("Undefined ctrl stmt '" + n.getText() + "'."); } _goto(go); } /** * Executa a extração do codigo baSeado na aSt, e retorna um objeto * CodigoTreSEnderecoS contendo oS blockS em Formato de treS endereçoS. * * @return * @throws Exception */ public Code getCodigoDeTresEnderecos() throws Exception { return run(); } /** * Ativa ou deSativa a otimizacao * * @param lc */ public void setOtimizacao(boolean lc) { code.setOtimizacao(lc); } protected void setMaster(Node n) { master.push(n); } protected Node getMaster() { return master.peek(); } protected void setNullMaster() { master.pop(); } protected int getIdMaster() throws Exception { if (master.empty()) { return 0; } return master.peek().GetInt("id"); } /** * Adiciona aS declaraçõeS bem como carregaoS parametroS e referenciaS * * @param n * @throws Exception */ protected void genPopParams(Node func) throws Exception { int reg = 0; String destino, atribuido, id; /** * Se for method declara e atribui o endereco a variavel */ Node receive = func.find("receive.type"); if (receive != null) { // atribuido = "_A" + (reg++); // destino = clearPointer(atribuido, CreateAlias(receive.childrens().Get(0))); destino = CreateVar(receive.childrens().get(0)); // copy_pointer? // Copy(Api.clearID(destino), __popParam().Get("_return"), false); __popParam(destino); } for (Node argument : func.find("arguments").childrens()) { for (Node arg : argument.find("ids").childrens()) { /** * Gera uma instrução de copia do registrador a{i},i = [0-4], * para o endereço de memoria dos parametros */ // atribuido = "_Ra" + (reg++); // atribuido = "_A" + (reg++); // System.out.println("PopArg:" + arg); // destino = clearPointer(atribuido, CreateAlias(arg)); // copy_pointer? // id = Api.clearID(CreateAlias(arg)); // Copy(id, __popParam(id).Get("_return"), false); __popParam(CreateVar(arg)); } } } protected Instruction __popParam(String varname) throws Exception { // String varname = CreateTmpVar(); // varname = Api.clearID(varname); varname = blockVarAliasCtx.peek().Reverse(varname); // System.out.println("Pop_Param:::::::" + varname + "::" + blockVarAliasCtx.peek()); Instruction param = Add(new Instruction() .Set("type", "pop_param") .Set("format", "pop_param") .Set("p1", varname) // .Set("p1", blockVarAliasCtx.peek().Reverse(varname)) .Set("p1value", "false") .Set("_return", varname)); // System.out.println("POP_PARAM:" + param); return param; } // protected void inicializarVariaveis() throws Exception { //// System.out.println("INICIALIZAR VARIAVEIS:"); // // for (Node container : ast.getRoot().childrens()) { // for (Node constant : container.findAll("dec::const,dec::var", "class", 1)) { // visit(constant); // } // } // } protected Instruction Copy(String dst, String src, boolean address) throws Exception { // String type; // Boolean dstIndexed = ArrayPatternRegex.matcher(dst).matches(), // srcIndexed = ArrayPatternRegex.matcher(src).matches(); // if (dstIndexed || srcIndexed) { // // type = "indexed_assign"; // //// inst.Set("src_indexed", srcIndexed); // inst.Set("src.indexed", srcIndexed); // inst.Set("dst.indexed", dstIndexed); // // if (srcIndexed) { // inst.Set("p1.indice", Api.getIndice(src)); // inst.Set("indice", Api.getIndice(src)); // } // // if (dstIndexed) { // inst.Set("dst.indice", Api.getIndice(dst)); // } if (ArrayPatternRegex.matcher(dst).matches()) { // System.out.println("@@@@Copy Store:" + dst + ":" + src); return Store(dst, src).Set("comment", String.format("Indexed copy %s <- %s", dst, src)); } else if (ArrayPatternRegex.matcher(src).matches()) { // System.out.println("@@@Load Store:" + dst + ":" + src); return Load(src, dst); } else { // Identifica que o valor copiado é um endereco ou valor return Add(new Instruction() .Set("format", "copy") .Set("type", "copy") .Set("src.address", address) .Set("dst", dst) .Set("p1", src)); } } /** * Gera um PuShLabel unico * * @return */ protected String gerarLabel() { // return code.genLabel(); return code.getCurrentBlockName() + "+_i" + (incLabel++); } /** * Cria uma linha de PuShLabel no block de codigo corrente * * @param label String * @throws Exception */ protected Instruction PushLabel(String label, String type) throws Exception { Instruction r = new Instruction() .Set("label", label) .Set("type", "label") .Set("label_type", type) .Set("format", "label") .Set("locker", getIdMaster()); return Add(r); } /** * Gera um nome de variavel unico, * * @param pre prefixo da variavel * @param n * @return */ protected String CreateAlias(String pre) { return "_" + pre + (tmpVarCount++); } protected String CreateTmpVar() { return CreateAlias("T"); } protected String CreateSavedVar() { return CreateAlias("S"); } protected String CreateVar(Node n) throws Exception { String id = n.getText(), alias; String[] g; if (!varGenMap.containsKey(id)) { g = SetNewVar(id, n); alias = g[0]; // System.out.println("id:" + id + "|g:" + alias); // if (alias.equals("_G5")) { // System.out.println("@@@@@@@@@@@@@@@ :" + id + " >>> " + alias + "::" + n.Get("id")); // } varGenMap.put(id, alias); if (varGenMap.containsKey(alias)) { if (id.length() < varGenMap.get(alias).length()) { varGenMap.put(alias, id); } } else { varGenMap.put(alias, id); } // Se for uma constante if (g[1].equals("t")) { return alias; } } id = varGenMap.get(id); BlockVarMap block = blockVarAliasCtx.peek(); if (!block.Defined(id)) { block.Put(id, CreateSavedVar()); // System.out.println("SET VAR (" + id + ")" + block.Get(id)); } return block.Get(id); } protected String[] SetNewVar(String id, Node n) throws Exception { Node var = Variables.Get(id); String uniqPath, alias, prefix; Integer elementCount; if (var == null) { throw new Exception(String.format("Var %s não definida", id)); } // Se for uma constante retorna o valor if (var.eq("constant", "true")) { return new String[]{var.Get("default.value"), "t"}; } // uniqPath = var.Get("scope") + "." + var.Get("name"); uniqPath = var.Get("name"); // System.out.println("UNIQUEPATH:" + uniqPath); // uniqPath = id; // System.out.println("$$$$$$$$$$$$4 VarName:" + uniqPath + "\n\n" + var); if (var.Has("alias")) { // Se a variavel possui um alias definido alias = var.Get("alias"); } else if (varGenMap.containsKey(uniqPath)) { // Se a variavel possui um alias definido no mapa de variaveis alias = varGenMap.get(uniqPath); } else { // Cria um novo alias para a variavel if (var.eq("global", "true")) { prefix = "G"; } else { // System.out.println("SETVAR" + var); String[] nameparts = var.Get("name").split("\\."); prefix = "V" + nameparts[nameparts.length - 1] .toUpperCase() .replace("_", "") .replace(" ", ""); } alias = CreateAlias(prefix); varGenMap.put(uniqPath, alias); if (varGenMap.containsKey(alias)) { if (uniqPath.length() < varGenMap.get(alias).length()) { varGenMap.put(alias, uniqPath); } } else { varGenMap.put(alias, uniqPath); } var.Set("alias", alias); // .Set("size", Types.Size(var.Get("type"))); n.Copy("pointer,alias", var); // vn = var.Get("scope"); elementCount = 1; // System.out.println("var:" + var); // System.out.println("gerarVariavelSetVAR:" + var); // Se for um array considera os filhos como index if (var.eq("array", "true") && var.childrens().size() > 0) { for (Node node : var.childrens()) { elementCount *= (node.eq("constant", "true") ? node.GetInt("default.value") : node.GetInt("value")); } } Alloc(var, elementCount); // System.out.println(">>>>>>>>>gerarVariavelSet(" + alias + "):" + var); // if (!isConstant || !var.in("type", primitives)) { // // Adiciona variaveis no frame global ou da funcao // } else { // alias = var.Get("default.value"); // } } return new String[]{alias, "f"}; } // // protected void DefineAliasInScope(String id, String alias, String scope) { // // String tmp = id.replace(scope, ""), // path = scope + "", // ; // // //// Matcher matcher = Pattern.compile(Variables.VARNAME).matcher(id); //// if (matcher.find()) { //// varname = matcher.group(); //// } //// System.out.println("DefineAliasInScope:\n " + id + ":\n " + scope + "\n: " + tmp + "\n: '" + varname + "'"); //// //// matcher = Pattern.compile(Variables.SCOPE_LEVE).matcher(tmp); //// //// while (matcher.find()) { //// scope += matcher.group(0); //// System.out.println("parh:" + scope); //// path = scope; //// } // } protected void Alloc(Node var, Integer numElements) throws Exception { DataLayout ctx; Instruction alloc; String alias = var.Get("alias"), type = var.Get("type"); Boolean global = alias.contains("_G"); if (global) { ctx = code.GlobalContext(); } else { ctx = code.Block().Context(); } if (!ctx.contains(alias)) { // System.out.println("Alloc(" + code.Block().getName() + "):" + alias + " > Numero:" + numElements); alloc = new Instruction() .Set("type", "alloc") .Set("format", "alloc") .Set("p1", alias) .Set("p1.type", type) .Set("numElements", numElements) .Set("locker", getIdMaster()); if (global) { // Adiciona a alocacao no bloco global code.Blocks().get("global").Add(alloc); } else { // Adiciona a alocacao no bloco atual code.Add(1, alloc); } ctx.Add(alias, type, numElements); } } /** * Imprime o codigo de treS endereçoS * * @return */ @Override public String toString() { return // printVarMap() code.toString(); } public String printVarMap() { StringBuilder s = new StringBuilder(); for (Map.Entry e : varGenMap.entrySet()) { s.append(e.getKey() + " : " + e.getValue() + "\n"); } System.out.println("Var Map:\n" + s.toString()); return varGenMap.toString(); } protected Instruction __gerarCall(String funcname, String numparam, int idMaster, Node returns) throws Exception { Instruction call = __gerarCall(funcname, numparam, idMaster); // Atribuição dos enderecos de retorn if (returns != null) { ArrayList rts = new ArrayList<>(); String t; for (Node r : returns.childrens()) { t = CreateTmpVar(); rts.add(t); Add(new Instruction() .Set("type", "pop_return") .Set("format", "pop_return") .Set("p1value", "false") .Set("p1", t)); } call.addList("returns", rts); } return call; } /** * Gera inStrução de call * * @param funcname * @param numparam * @param idMaster * @param variavelRetorno * @throws Exception */ protected Instruction __gerarCall(String funcname, String numparam, int idMaster) throws Exception { Instruction r = new Instruction(); r.Set("format", "call") .Set("type", "call") .Set("funcname", funcname) .Set("numParams", numparam).Set("locker", idMaster); Add(r); return r; } // protected void basicBlockSet(Instruction inst) throws Exception { //// String type = inst.Get("type"); // // if (resetOnNextAdd || inst.eq("type", "label")) { // System.out.println("Reset por (" + resetOnNextAdd + ") or era label"); // blockVarAliasCtx.peek().Reset(); // resetOnNextAdd = false; // return; // } //// switch (inst.Get("type")) { //// case "jump": //// case "call": //// case "goto": //// case "branch": //// resetOnNextAdd = true; //// } // } protected Instruction Add(Instruction inst) throws Exception { Instruction load = null; String value; String[] parts; String type, paramValue; // basicBlockSet(inst); if (inst.eq("type", "label")) { blockVarAliasCtx.peek().Reset(); ArrayShiftMap = new HashMap<>(); } boolean temporary, ignore = !inst.in("type", new String[]{"jump", "goto", "label"}); // Inseri a carga dos parametros if (ignore) { //Update types of address for (String param : new String[]{"dst", "p1", "p2"}) { if (!inst.Has(param)) { continue; } type = "int32"; paramValue = inst.Get(param); if (varGenMap.containsKey(paramValue)) { type = Variables.TypeOf(varGenMap.get(paramValue)); // System.out.println("Check type for " + paramValue + "|" + varGenMap.get(paramValue) + "|" + type); } inst.Set(param + ".type", type); if (!inst.Has(param + "value")) { inst.Set(param + "value", Api.IsValue(paramValue) + ""); } } // if (!inst.in("type", "load,store".split(","))) { if (!inst.in("type", "load,pop_param".split(","))) { // load params when necessary for (String param : new String[]{"p1", "p2"}) { if (!inst.Has(param)) { continue; } temporary = inst.contem(param, "_T"); paramValue = inst.Get(param); // temporary = paramValue.matches("_(T|S)\\d*"); // System.out.println("Temporary(" + paramValue + "):" + temporary); // System.out.println("Param(" + param + "|" + paramValue + "):" + inst.eq(param + "value", "false")); if (!temporary && !inst.eq(param + "value", "true")) { if (!blockVarAliasCtx.peek().Loaded(paramValue)) { load = Load( paramValue, // Esse atributo sera reverdido para o endereco da variavel paramValue ).Set("comment", "Load param (" + param + ":" + paramValue + ")"); } } } } } // Se a instrução adicionada for uma copia e o parametro foi carregado // Atualiza o destino para o destino da copia e não adiciona a copia if (inst.eq("type", "copy") && load != null) { load.Set("dst", inst.Get("dst")); return load; } else { // Adiciona a instrução code.Add(inst .Set("inloop", loopScope.peek()) .Set("locker", getIdMaster()) ); } // // if (inst.eq("type", "store")) { // System.out.println("Add store" + inst); // blockVarAliasCtx.peek().SetLoaded(inst.Get("p1"), false); // } // System.out.println("entrei do loop - " + inst.Get("type")); for (String param : "dst,p1,p2".split(",")) { if (inst.Has(param)) { value = inst.Get(param); // System.out.println("value:(" + param + ")" + value + ":" + inst); parts = value.split("\\["); if (parts.length > 1) { // System.out.println("Set " + param + ".indexed: true"); // System.out.println("Set " + param + ".indice:" + parts[1].replace("]", "")); // System.out.println("param.concat(\".indexed\"):" + param.concat(".indexed")); inst.Set(param.concat(".indexed"), "true") .Set(param.concat(".indice"), parts[1].replace("]", "")); //// i.Set(param + ".indice", parts[1].replace("]", "")); } } } if (!inst.in("type", "store,load".split(","))) { // Se existe um destino e ele não for temporario // persiste o valor copiado para o destino // if (inst.Has("dst") && !inst.Get("dst").split("\\[")[0].contains("_T")) { if (inst.Has("dst") && !inst.Get("dst").split("\\[")[0].contains("_T")) { // if (i.Has("dst") && !i.Get("dst").matches("^_T\\d+(\\[\\w+\\])?")) { // String dst = Utils.clearName(inst.Get("dst")); // dst = blockVarAliasCtx.peek().Reverse(dst); // System.out.println("dst:" + dst); // System.out.println("TYPE OF1:" + dst); // System.out.println("TYPE OF2:" + varGenMap.get(dst)); // System.out.println("TYPE OF3" + Variables.TypeOf(varGenMap.get(dst))); Store(inst.Get("dst"), inst.Get("p1")); if (inst.eq("dst.indexed", "true")) { // //Se o destino for indexdo sempre é um byte inst.Set("dst.type", "byte"); // i.Set("dst.type", "byte"); } } } switch (inst.Get("type")) { case "jump": case "call": case "goto": case "branch": // resetOnNextAdd = true; blockVarAliasCtx.peek().Reset(); ArrayShiftMap = new HashMap<>(); } return inst; } protected Stack blockVarAliasCtx = new Stack() { { add(new BlockVarMap()); } }; protected boolean resetOnNextAdd = false; private static class BlockVarMap { protected static String prefix = "@"; protected HashMap map = new HashMap<>(); protected HashMap loaded = new HashMap<>(); public BlockVarMap() { } public void Put(String var, String alias) { // System.out.println("$$$$$$$$$$$$$$$$ PUT " + var + " : " + alias); var = Utils.clearName(var); map.put(var, alias); map.put(prefix + alias, var); } public boolean Defined(String var) { var = Utils.clearName(var); return map.containsKey(var) || map.containsKey(prefix + var); } public String Get(String var) { var = Utils.clearName(var); return map.get(var) + FixIndex(var); } public String Reverse(String alias) { // System.out.println("$$$$$$$$$$$$$$$$ Get Reverse of " + (prefix + Utils.clearName(alias)) + " | " + map); return map.get(prefix + Utils.clearName(alias)) + FixIndex(alias); } public void Reset() { // System.out.println("$$$$$$$$$$$$$$$$ RESET "); map = new HashMap<>(); loaded = new HashMap<>(); } @Override public String toString() { return map.toString(); } protected boolean Loaded(String alias) { // System.out.println("$$$$$$$$$$$$$$$$ LOADED " + alias + " : " + (loaded.containsKey(alias) && loaded.get(alias))); return loaded.containsKey(alias) && loaded.get(alias); } protected void SetLoaded(String alias) { SetLoaded(alias, true); } private void SetLoaded(String alias, boolean b) { // System.out.println("$$$$$$$$$$$$$$$$ SetLoaded:" + alias + ":" + b); loaded.put(alias, b); } protected String FixIndex(String alias) { String i = Api.getIndice(alias); if (!i.equals("")) { return "[" + i + "]"; } return ""; } } }