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.Code; 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; // Atualizei as labels mas não atualizei as referencias por isso esta sendo removida quando faz a limpeza /** * * @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 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(false); } }; 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("(\\&|\\*)"); 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); // Especifica o template engine code.Template(new IRTemplate()); } // public void DeclareConstants(Node root) throws Exception { //// System.out.println("DeclareConstants() ..."); // for (Node constants : root.findAll("dec.const", "class", 0)) { //// System.out.println("Declare constant ..." + constants); // visit(constants); // } // } @Override public Code Create(AbstractSyntaxTree ast) throws Exception { Ast(ast); // DeclareConstants(ast.getRoot()); // setOtimizacao(settings.Get("clearCode").equals("true")); 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); Node var = Variables.Get(n.getText()); n.Set("_return", gerarVariavel(var)); } 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 = gerarVariavel(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 = gerarVariavel(n); if (n.eq("pointer", "*") && n.eq("access", "read")) { String t = gerarVariavel("T"); 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 = gerarVariavel(n) + "[" + shift + "]"; if (!n.eq("access", "write")) { String t = gerarVariavel("T"); 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 int Size(String type) throws Exception { return Types.Size(type) * 4; } 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()) { key += "_" + node.getText(); } 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(), 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, gerarVariavel(n), ret); // shift = ret; // } ArrayShiftMap.put(key, ret); } return ArrayShiftMap.get(key); } 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 = gerarVariavel("T"), T2 = gerarVariavel("T"), T3 = gerarVariavel("T"); switch (path.size()) { case 1: if (!mps) { Copy(T1, var, false) .Set("comment", "Copy value of index") .Set("copy", "true"); } else { T1 = var; } if (!last) { __exp("<<", T1, "" + pow2(size), T2).Set("comment", ""); return T2; } return T1; case 3: op1 = path.remove(0); operacao = path.remove(0); op2 = path.remove(0); // String T4 = gerarVariavel("T"); if (!mps) { Copy(T1, var, false) .Set("comment", "Copy value of index") .Set("copy", "true"); } if (op1 != 1) { __exp("<<", T1, "" + pow2(op1), T1).Set("comment", ""); } // if (op2 == 1) { // } else { // Copy(T3, var, false).Set("comment", "Copy value of index"); if (op2 != 1) { // System.out.println("GSLL:" + op2 + ":" + op1); // System.out.println("GSLL:op2" + pow2(op2)); // System.out.println("GSLL:op1" + pow2(op1)); __exp("<<", T1, "" + (pow2(op2) - pow2(op1)), T2).Set("comment", ""); // 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; 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 = gerarVariavel( new Node(gerarVariavel("TMP")) .Set("array", "false") .Set("type", "int") .Set("var.tmp", "true") ); 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 = gerarVariavel(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); } } int 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); // multPerSize = false; } else { // System.out.println("collNumber:" + collNumber); // current = GenShiftLeftLogical(gerarVariavel(ind), collNumber, false, false); current = GenShiftLeftLogical(varname, collNumber, false, false); // System.out.println("Gerando index calc:" + retl); // current = GenShiftLeftLogical(retl, Size); // current = retl; } String ret = CalcArrayAddressAux(childrens, Size); __exp("+u", current, ret, current).Set("comment", "colls shift"); // if (multPerSize) { // // Realiza a multiplicacao pelo tamanho do elemento // current = GenShiftLeftLogical(current, Size); // } return current; } // protected String CalcArrayAddress(ArrayList childrens, int Size, int index) throws Exception { // System.out.println("CalcArrayAddress:" + childrens.size() + ":" + Size); // // int nindex = index + 1; // String retl; // Node ind = childrens.remove(0); // if (childrens.size() >= 1) { // String ret = CalcArrayAddress(childrens, Size, nindex); // int collNumber = ind.getInt("collNumber"); // // if (Utils.IsNumber(ret) && ind.IsNumber("value")) { //// System.out.println("CalcArray:" + ind.getInt("value") + ":" + ind.getInt("collNumber") + ":" + Integer.parseInt(ret)); // return "" + ((ind.getInt("value") * collNumber) + Integer.parseInt(ret)); // } else { //// System.out.println("collNumber:" + collNumber); // // retl = GenShiftLeftLogical(gerarVariavel(ind), collNumber); // // retl = GenShiftLeftLogical(retl, Size); // // __exp("+", retl, ret, retl).Set("comment", "colls shift"); // return retl; // } // // /* // Implementacao com mult ** // int collNumber = ind.getInt("collNumber"); // // if (Utils.IsNumber(ret) && ind.IsNumber("value")) { // System.out.println("CalcArray:" + ind.getInt("value") + ":" + collNumber + ":" + Integer.parseInt(ret)); // return "" + ((ind.getInt("value") * collNumber) + Integer.parseInt(ret)); // } else { // String retl = gerarVariavel("T"); // __exp("*", gerarVariavel(ind), "" + collNumber, retl) // .Set("comment", "lines shift"); // __exp("+", retl, ret, retl) // .Set("comment", "colls shift"); // return retl; // } // */ // } else { // // if (Utils.IsNumber(ind.getText())) { // return ind.getText(); // } else { // // ultimo elemento da idexacao // // return GenShiftLeftLogical(gerarVariavel(ind), Size); // } // // } // } /** * 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)); // gerarVariavel(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); } } } code.UpdatePositions(); return code; } /** * ProceSSa If (ElSe'Set)* * * @param n * @throws Exception */ protected void IfStmts(Node n) throws Exception { String end = gerarLabel(), next; boolean ifChain = n.childrens().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); 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) 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) { // 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 { r1.Set("format", "branch") .Set("type", "branch") .Set("op", op) .Set("p1", p0) .Set("p2", p1) .Set("p1value", "" + p0IsValue) .Set("p2value", "" + Api.IsValue(p1)); Add(r1); } // System.out.println("Add branch:" + branckInvert.peek() + branckInvert + ">>" + (!branckInvert.isEmpty() && branckInvert.peek()) + "\n" + r1); return r1; } protected Instruction Store(String attr) throws Exception { return Add(new Instruction().Set("type", "store").Set("format", "memory").Set("p1", attr)); } protected Instruction Load(String attr) throws Exception { return Add(new Instruction().Set("type", "load").Set("format", "memory").Set("p1", attr)); } protected Instruction Add(Instruction i) throws Exception { // System.out.println("ADD:" + i); String loop = "" + loopScope.peek(), type, paramValue; boolean temporary, ignoreLoadStore = !i.in("type", new String[]{"jump", "goto", "label"}); // Inseri a carga dos parametros if (ignoreLoadStore) { for (String param : new String[]{"p1", "p2"}) { if (!i.Has(param)) { continue; } temporary = i.contem(param, "_T"); paramValue = i.Get(param); if (!temporary && i.eq(param + "value", "false")) { Load(paramValue).Set("inloop", loop); } if (i.isNumber(param)) { continue; } if (temporary) { type = "int32"; } else { // System.out.println("ADD:TYPEOF:" + paramValue + ":" + varGenMap.get(paramValue)); type = Variables.TypeOf(varGenMap.get(paramValue)); } // System.out.println(param + ".type = " + type); i.Set(param + ".type", type); } } // Adiciona a instrução code.Add(i.Set("inloop", loop)); if (i.Has("dst") && !i.contem("dst", "_T")) { Store(i.Get("dst")).Set("inloop", loop); } // .Set("basicBlock", basicBlock.peek() + "." + basicBlockCount.peek()) return i; } protected Instruction Branch(Node n, int index) throws Exception { Instruction instruction = null; // System.out.println("test:" + n); // ArrayList childrens = n.parent.childrens(); // if (childrens.size() > 1) { //// visit(childrens.Get(0)); // Node c = n; // n = childrens.Get(1); // n.copy("test.type,next,start,end", c); // } // System.out.println("n:" + n); 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(true); 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*/ 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); } 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 = gerarVariavel("T"); 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); 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); } /*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) 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(); } // /*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.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); /*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)); } } 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)); // } } 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"); 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(); // 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("&" + gerarVariavel(var)); // Add(new Instruction() // .Set("", PushLabel)); // gerarVariavel(var) __genParam(gerarVariavel(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 = gerarVariavel("T"); // 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, gerarVariavel(receive.childrens().Get(0))); destino = gerarVariavel(receive.childrens().get(0)); // copy_pointer? // Copy(Api.clearID(destino), __popParam().Get("_return"), false); __popParam(Api.clearID(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, gerarVariavel(arg)); // copy_pointer? // id = Api.clearID(gerarVariavel(arg)); // Copy(id, __popParam(id).Get("_return"), false); __popParam(Api.clearID(gerarVariavel(arg))); } } } protected Instruction __popParam(String varname) throws Exception { // String varname = gerarVariavel("T"); Instruction r = new Instruction() .Set("type", "pop_param") .Set("format", "pop_param") .Set("p1", varname) .Set("p1value", "false") .Set("_return", varname); r.Set("locker", getIdMaster()); Add(r); return r; } // 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 { // System.out.println("TAC:Copy:" + dst + "=" + src); String type, format, arrayPattern = ".*\\[.*\\]"; Instruction r = new Instruction(); if (dst.matches(arrayPattern) || src.matches(arrayPattern)) { type = "indexed_assign"; format = "copy"; if (Variables.isArray(src)) { r.Set("src_indexed", "true"); r.Set("p1.indice", Api.getIndice(src)); } if (Variables.isArray(dst)) { r.Set("dst_indexed", "true"); r.Set("dst.indice", Api.getIndice(dst)); } else { r.Set("dst_indexed", "false"); } if (Variables.isArray(src)) { r.Set("indice", Api.getIndice(src)); } } else { type = format = "copy"; } // Identifica que o valor copiado é um endereco ou valor if (address) { r.Set("src.address", "true"); } r.Set("format", format) .Set("type", type) .Set("dst", dst) .Set("p1", src) .Set("p1value", Api.IsValue(src) + "") .Set("locker", getIdMaster()); Add(r); return r; } /** * Gera um PuShLabel unico * * @param n * @return */ protected String gerarLabel(Node n) { // return code.genLabel(); return code.getCurrentBlockName() + "+_i" + (incLabel++); } 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 gerarVariavel(String pre) { return "_" + pre + (tmpVarCount++); } protected String gerarVariavel(Node n) throws Exception { String id = n.getText(), g; if (!varGenMap.containsKey(id)) { g = gerarVariavelSet(id, n); varGenMap.put(id, g); varGenMap.put(g, id); } return varGenMap.get(id); } protected String gerarVariavelSet(String id, Node n) throws Exception { Node var = Variables.Get(id); String varname, alias, vn; if (var != null) { if (var.eq("constant", "true")) { varname = id; } else { varname = var.getText(); } // System.out.println("Variavel definida:" + varname); } else { varname = n.getText(); var = n; // System.out.println("Variavel do no consultado:" + varname); // Variables.Add(id, n); } // System.out.printf("GerarVariavelSet{%s\n,%s\n,%s\n}\n", id, varname, var); // if (var.eq("constant", "true")) { // System.out.printf("GerarVariavelSet{%s\n,%s\n,%s\n}\n", id, varname, var); // } if (varGenMap.containsKey(varname)) { alias = varGenMap.get(varname); // System.out.printf("GerarVariavelSet[MAPPED]{%s,%s}\n", varname, alias); } else { String prefix; // System.out.println("GerarVariavelSet\n" + varname + "\n" + id + "\n" + var); if (var.eq("class", "dec.const")) { prefix = "C"; } else if (var.eq("global", "true")) { prefix = "G"; } else if (var.eq("var.tmp", "true")) { prefix = "T"; } else { prefix = "V"; } // System.out.println("gerarVariavelSet:" + id + var); // System.out.println("DecVar:" + var); // alias = var.Get("pointer") + gerarVariavel(prefix); alias = gerarVariavel(prefix); n.Set("alias", alias); n.copy("pointer", var); varGenMap.put(varname, alias); varGenMap.put(alias, varname); // vn = var.Get("scope"); // System.out.println("var:" + var); int size = Types.Size(var.Get("type")), elementCount = 1; var.Set("size", size); // 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()) { // System.out.println("gerarVariavelSetArray:" // + node.eq("constant", "true") // + "\n" + node // + "\nVARIABLE:\n" + var // ); elementCount *= (node.eq("constant", "true") ? node.getInt("default.value") : node.getInt("value")); } } // size *= elementCount; if (!var.eq("constant", "true") || !var.in("type", primitives)) { // Adiciona variaveis no frame global ou da funcao (prefix.equals("G") ? code.GlobalData() : code.Block().Data()) .Add(alias, var, elementCount); } else { alias = var.Get("default.value"); } } return alias; } /** * 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(); } /** * Executa a extração da aSt para codigo de treS endereçoS * * @throws Exception */ public void extrair() throws Exception { if (!inicializado) { inicializado = true; } // inicializarVariaveis(); // extrairTraps(); // extrairThreads(); // extractFunctions(); // extracMethods(); main(); } 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 = gerarVariavel("T"); 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("nump", numparam).Set("locker", idMaster); // if (!variavelRetorno.equals("")) { // r.Set("dst", variavelRetorno); // } Add(r); return r; } } // case "||": // and = false; // // Não deve inverter operacao no caso de || // branckInvert.push(and); // // _or(n); // // Branch(x.Get(0)); // Branch(x.Get(1)); // // // Inverte a ultima operacao // if (n.parent.eq("value", "||")) { // } // //// if (!loop && branckInvert.size() == 1) { //// Instruction last = code.Last(); //// last.Set("op", Utils.ComplementOperation(last.Get("op"))).Set("label", n.Get("next")); //// } // if (!x.Get(0).Has("and")) { // n.remove("and"); // } // branckInvert.pop(); // // break; // default: //// boolean empty = branckInvert.isEmpty(); //// //// if (empty) { //// branckInvert.push(true); //// } // // 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 { //(<, <=, >, >=, ==, !=) // p0 = visit(x.Get(0)).Get("_return"); // p1 = visit(x.Get(1)).Get("_return"); // } // // Instruction instruction = Branch(op, p0, p1, n.Get("next")); //// instruction. ; //// if (n.Has("false")) { // // _goto(n.Get("false")); // // } // // if (empty) { // // branckInvert.pop(); // // } // @Override // public IRGenInterface AfterCreate(CodeProcessing p) { // this.afterCreate.add(p); // return this; // } // // public IRGenInterface AfterCreate() throws Exception { // for (CodeProcessing x : afterCreate) { // x.Exec(code); // } // return this; // } // protected Instruction Branch(String op, final String p1, final String p2, String label) throws Exception { // // Instruction r1 = new Instruction(); // r1.Set("format", "branch") // .Set("type", "branch") // .Set("op", op) // .Set("p1", p1) // .Set("p2", p2) // .Set("p1value", "" + Api.IsValue(p1)) // .Set("p2value", "" + Api.IsValue(p2)) // .Set("label", label); // //// System.out.println("Add branch:" + branckInvert.peek() + branckInvert + ">>" + (!branckInvert.isEmpty() && branckInvert.peek()) + "\n" + r1); // Add(r1); // return r1; // } // /** // * ProceSSa um teSte logico AND // * // * @param n // * @throws Exception // */ // protected void _and(Node n) throws Exception { // String attrs = "next,start,end,test,skip.test"; // Node b1 = n.getFilho(0).copy(attrs, n); // Node b2 = n.getFilho(1).copy(attrs, n); // //// boolean isFor = n.eq("test.type", "for"); //// System.out.println("_AND{" + isFor + "}:" + n.Get(isFor ? "and" : "next")); //// String l = n.Get(n.eq("test.type", "for") ? "and" : "next"); // b1.Set("true", n.Get("next")); //// b1.Set("false", b.Get("false")); //// System.out.println("_AND:" + label + "-s" + b1); // b2.Set("true", n.Get("next")); //// b2.Set("false", b.Get("false")); //// b1.Set("true", gerarLabel()); //// b1.Set("false", b.Get("false")); //// //// b2.Set("true", b.Get("true")); //// b2.Set("false", b.Get("false")); // } // /** // * ProceSSa um teSte logico OR // * // * @param n // * @throws Exception // */ // protected void _or(Node n) throws Exception { // // String attrs = "next,start,end,test,skip.test"; // Node b1 = n.getFilho(0).copy(attrs, n); // Node b2 = n.getFilho(1).copy(attrs, n); // // b1.Set("true", n.Get("start")); // b2.Set("true", n.Get("start")); // // }// // protected String updateLabel(Node n) { // String PushLabel = n.Get("_return"); //// if (!PushLabel.substring(0, 1).equals("_R")) { //// } //// n.Set("_return", PushLabel); // return PushLabel; // }