-- -- Tree Pattern Language Specification for a pseudo RISC -- like target architecture. Only basic things have been -- implemented (e.g. function und procedure calls are missing -- in this example specification) -- generator (: import slcomp.parser.Type; import slcomp.parser.Obj; import slcomp.parser.Kind; import slcomp.ir.hir.HirNode; import static slcomp.ir.hir.HirNodeKind.*; import java.util.LinkedList; import java.util.List; :) declarations (: private static int nlab = 1; // next numeric value for a label e.g.: $L1, $L2, etc. private static int nreg = 0; // next numeric value for a register e.g.: r1, r2, etc. /** * funLabel(): Generates Labels for functions */ private static String funLabel(String name, Obj o) { if (o != null && o.kind == Kind.PARAM) { StringBuffer fname = new StringBuffer(name + "_" + o.type); while (o.next != null && o.next.kind == Kind.PARAM) { fname.append("_" + o.next.type); o = o.next; } return fname.toString(); } else { return name; } } /** * nlab(): returns the next label. */ public static String nlab() { return "$L" + nlab++; } /** * nreg(): returns the next register. */ private static String nreg() { return "r" + ++nreg; } :) operators -- Entry Points ROOT, ROOTDEF, -- Variables and Constants CONST, VAR, -- Arithmetic Operators ADD, SUB, MULT, DIV, MOD, -- Comparison Operators EQ, LEQ, GEQ, LTH, GTH, -- Control Flow IF, IFELSE, ELSEIF, WHILE, RETURN, -- ASSIGN, -- Functions with and without parameters FUN, FUNPARAM, -- Void Functions with and without parameters SIDEFFECT, SIDEFFECTPARAM, -- Procedure and Procedure definition label PROC, ENTER rules -- -- Start node: First definition is the start definition -- root <: out StringBuffer buf :> (: buf = new StringBuffer("# AUTOGENERATED CODE\n"); :) = ROOT (stmtseq <. out List seq .> (: buf.append("main:\n"); for (Instruction t : seq) buf.append(t.code + "\n"); :) ) : 0 | ROOTDEF (fundefseq <: out List defs :> , (: for (StringBuffer s : defs) buf.append(s + "\n"); :) stmtseq <: out List seq :> (: buf.append("main:\n"); for (Instruction t : seq) buf.append(t.code + "\n"); :) ) : 0 . -- -- stmts -- stmtseq <: out List il :> (: il = new LinkedList(); :) = stmt <: out Instruction stmt :> (: il.add(stmt); :) [ stmtseq <: out List ilseq :> (: il.addAll(ilseq); :) ] : 0 . stmt <: out Instruction stmt :> (: stmt = new Instruction(); :) = IF (cond <: out Instruction cond :>, stmtseq <: out List seq :> ) (: stmt.reg = null; stmt.code.append("# IF\n"); String nstmts = nlab(); // label to stmts after if String next = nlab(); // next label // emit condition stmt.code.append("# COND START \n") .append(cond.code + "\n") .append(" cbr " + cond.reg + "," + next + "," + nstmts + "\n# COND END\n") .append(next + ":\n"); // emit then stmt.code.append("# THEN\n"); for (Instruction t : seq) stmt.code.append(t.code + "\n"); // emit place to jump to if cond evaluated to 'False' stmt.code.append("# IF END\n" + nstmts + ":\n nop\n"); :) : 1 | (: String label = nlab(); // label of next stmts :) IFELSE (elseifseq <: out List stmts, String label.fld :>, stmtseq <: out List seq :>) (: stmt.reg = null; stmt.code.append("# IFELSE\n"); // append 'ELSEIF's for (StringBuffer b : stmts) stmt.code.append(b + "\n"); // emit else stmts for (Instruction t : seq) stmt.code.append(t.code + "\n"); // emit label where next stmts start stmt.code.append(label + ": \n") .append("# IFELSE END\n"); :) : 2 | WHILE (cond <: out Instruction c :>, stmtseq <: out List seq :> ) (: stmt.reg = null; String nstmts = nlab(); // label to stmts after loop String next = nlab(); // next label String whileLab = nlab(); // label pointing to while loop // emit conds stmt.code.append("# WHILE LOOP START\n") .append(whileLab + ":\n") .append("# COND START\n") .append(c.code + "\n") .append(" cbr " + c.reg + "," + next + "," + nstmts + "\n# COND END\n") .append(next + ":\n"); // emit while body stmt.code.append("# LOOP BODY START\n"); for (Instruction t : seq) stmt.code.append(t.code + "\n"); // emit jump back to where loop starts stmt.code.append(" j " + whileLab + " # JUMP BACK TO WHILE LOOP COND\n"); // emit place to jump to if cond evaluated to 'False' stmt.code.append("# WHILE LOOP END\n" + nstmts + ":\n nop\n"); :) : 2 | RETURN (exp <: out Instruction exp :>) (: stmt.reg = "$retreg"; stmt.code.append(exp.code + "\n"); stmt.code.append(" ld " + stmt.reg + "," + exp.reg); :) : 2 | assign <: out Instruction a :> (: stmt.reg = a.reg; stmt.code = a.code; :) : 0 | sideffect <: out StringBuffer s :> (: stmt.reg = null; stmt.code = s; :) : 0 . -- -- ELSEIF handling -- elseifseq <: out List stmts, String label :> (: stmts = new LinkedList(); :) = elseif <: out StringBuffer stmt, String label :> (: stmts.add(stmt); :) [ elseifseq <: out List s2, String label :> (: stmts.addAll(s2); :) ] : 0 . elseif <: out StringBuffer stmts, String label :> (: stmts = new StringBuffer(); :) = ELSEIF (cond <: out Instruction c :>, stmtseq <: out List seq :> ) (: stmts.append("# ELSEIF\n"); String nstmts = nlab(); // label to stmts after if String next = nlab(); // next label // emit cond stmts.append("# COND START \n") .append(c.code + "\n") .append(" cbr " + c.reg + "," + next + "," + nstmts + "\n# COND END\n") .append(next + ":\n"); // emit then stmts.append("# THEN\n"); for (Instruction t : seq) stmts.append(t.code + "\n"); // after we are done here we need to jump to 'label' stmts.append(" j " + label + "\n"); // emit place to jump to if cond evaluated to 'False' stmts.append("# ELSEIF END\n" + nstmts + ":\n nop\n"); :) : 1 . -- -- Function Call (e.g. function which returns value) -- fun <: out Instruction fun :> (: fun = new Instruction("$retreg"); :) = FUN (PROC p) (: fun.code.append(" jal " + funLabel(((HirNode)p).name, ((HirNode)p).obj) + " # CALL"); :) : 2 | FUNPARAM (PROC p , exp <: out Instruction exp :>) (: fun.code.append(exp.code + "\n"); // @TODO: we would need to setup the call parameters here fun.code.append(" jal " + funLabel(((HirNode)p).name, ((HirNode)p).obj) + " # CALL"); :) : 3 . -- -- Sideeffect (e.g. function which returns void) -- sideffect <: out StringBuffer se :> (: se = new StringBuffer(); :) = SIDEFFECT (PROC p) (: se.append(" jal " + funLabel(((HirNode)p).name, ((HirNode)p).obj) + " # CALL"); :) : 2 | SIDEFFECTPARAM (PROC p, exp <: out Instruction exp :>) (: se.append(exp.code + "\n"); // @TODO: we would need to setup the call parameters here se.append(" jal " + funLabel(((HirNode)p).name, ((HirNode)p).obj) + " # CALL").toString(); :) : 3 . proc = PROC : 1. -- -- Function defition -- fundefseq <: out List il :> (: il = new LinkedList(); :) = fundef <: out StringBuffer il1 :> (: il.add(il1); :) [ fundefseq <: out List il2 :> (: il.addAll(il2); :) ] : 0 . fundef <: out StringBuffer buf :> (: buf = new StringBuffer("# PROC DEFINITION:\n"); :) = ENTER e1 ( (: buf.append(((HirNode)e1).name + ":\n"); :) stmtseq <: out List seq :> (: for (Instruction t : seq) buf.append(t.code + "\n"); // return from function call buf.append(" jr $r31\n"); :) ) : 0 . -- -- Assignment -- assign <: out Instruction a :> (: a = new Instruction(); :) = ASSIGN (var <: out String vout :> v , exp <: out Instruction exp :>) (: a.reg = vout; a.code.append(exp.code + "\n") .append(" sw " + a.reg + "," + exp.reg); :) : 2 . -- -- Value -- val <: out String val :> (: val = null; :) = num <: out String num :> (: val = num; :) : 0 | var <: out String var :> (: val = var; :) : 0 . -- -- Primitive stuff like number and variable -- num <: out String num :> = CONST c (: num = ((HirNode)c).name; :) : 1 . var <: out String var :> = VAR v (: var = "@" + ((HirNode)v).name; :) : 1 . -- -- exp -- exp <: out Instruction exp :> (: exp = new Instruction(); :) = arit <: out Instruction a :> (: exp.reg = a.reg; exp.code.append(a.code + "\n"); :) : 0 | cond <: out Instruction cond :> (: exp.reg = cond.reg; exp.code.append(cond.code + "\n"); :) : 0 | val <: out String val :> (: exp.reg = nreg(); exp.code.append(" li " + exp.reg + "," + val); :) : 0 | fun <: out Instruction fun :> (: exp.reg = fun.reg; exp.code = fun.code; :) : 0 . -- -- Conditions (EQ, LEQ, GEQ, LTH, GTH) -- cond <: out Instruction cond :> (: cond = new Instruction(nreg()); :) = EQ (exp <: out Instruction e1 :>, exp <: out Instruction e2 :>) (: cond.code.append(e1.code + "\n") .append(e2.code + "\n") .append(" seq " + cond.reg + "," + e1.reg + "," + e2.reg); :) : 2 | LEQ (exp <: out Instruction e1 :>, exp <: out Instruction e2 :>) (: cond.code.append(e1.code + "\n") .append(e2.code + "\n") .append(" sle " + cond.reg + "," + e1.reg + "," + e2.reg); :) : 2 | GEQ (exp <: out Instruction e1 :>, exp <: out Instruction e2 :>) (: cond.code.append(e1.code + "\n") .append(e2.code + "\n") .append(" sge " + cond.reg + "," + e1.reg + "," + e2.reg); :) : 2 | LTH (exp <: out Instruction e1 :>, exp <: out Instruction e2 :>) (: cond.code.append(e1.code + "\n") .append(e2.code + "\n") .append(" slt " + cond.reg + "," + e1.reg + "," + e2.reg); :) : 2 | GTH (exp <: out Instruction e1 :>, exp <: out Instruction e2 :>) (: cond.code.append(e1.code + "\n") .append(e2.code + "\n") .append(" sgt " + cond.reg + "," + e1.reg + "," + e2.reg); :) : 2 . -- -- Arithmetic (ADD, SUB, MULT, DIV, MOD) -- arit <: out Instruction arit :> (: arit = new Instruction(nreg()); :) = ADD (arit <: out Instruction a1 :>, arit <: out Instruction a2 :>) (: arit.code.append(a1.code + "\n") .append(a2.code + "\n") .append(" add " + arit.reg + "," + a1.reg + "," + a2.reg); :) : 1 | ADD (val <: out String v :>, arit <: out Instruction a :>) (: arit.code.append(a.code + "\n") .append(" addi " + arit.reg + "," + a.reg + "," + v); :) : 1 | ADD (arit <: out Instruction a :>, val <: out String v :>) (: arit.code.append(a.code + "\n") .append(" addi " + arit.reg + "," + a.reg + "," + v); :) : 1 | ADD (val <: out String v1 :>, val <: out String v2 :>) (: String temp = nreg(); arit.code.append(" li " + temp + "," + v1 + "\n") .append(" addi " + arit.reg + "," + temp + "," + v2); :) : 1 -- SUB | SUB (arit <: out Instruction a1 :>, arit <: out Instruction a2 :>) (: arit.code.append(a1.code + "\n") .append(a2.code + "\n") .append(" sub " + arit.reg + "," + a1.reg + "," + a2.reg); :) : 1 | SUB (val <: out String v :>, arit <: out Instruction a :>) (: arit.code.append(a.code + "\n") .append(" subi " + arit.reg + "," + a.reg + "," + v); :) : 1 | SUB (arit <: out Instruction a :>, val <: out String v :>) (: arit.code.append(a.code + "\n") .append(" subi " + arit.reg + "," + a.reg + "," + v); :) : 1 | SUB (val <: out String v1 :>, val <: out String v2 :>) (: String temp = nreg(); arit.code.append(" li " + temp + "," + v1 + "\n") .append(" subi " + arit.reg + "," + temp + "," + v2); :) : 1 -- MULT | MULT (arit <: out Instruction a1 :>, arit <: out Instruction a2 :>) (: arit.code.append(a1.code + "\n") .append(a2.code + "\n") .append(" mult " + arit.reg + "," + a1.reg + "," + a2.reg); :) : 1 | MULT (val <: out String v :>, arit <: out Instruction a :>) (: arit.code.append(a.code + "\n") .append(" multi " + arit.reg + "," + a.reg + "," + v); :) : 1 | MULT (arit <: out Instruction a :>, val <: out String v :>) (: arit.code.append(a.code + "\n") .append(" multi " + arit.reg + "," + a.reg + "," + v); :) : 1 | MULT (val <: out String v1 :>, val <: out String v2 :>) (: String temp = nreg(); arit.code.append(" li " + temp + "," + v1 + "\n") .append(" multi " + arit.reg + "," + temp + "," + v2); :) : 1 -- DIV | DIV (arit <: out Instruction a1 :>, arit <: out Instruction a2 :>) (: arit.code.append(a1.code + "\n") .append(a2.code + "\n") .append(" div " + arit.reg + "," + a1.reg + "," + a2.reg); :) : 1 | DIV (val <: out String v :>, arit <: out Instruction a :>) (: arit.code.append(a.code + "\n") .append(" divi " + arit.reg + "," + a.reg + "," + v); :) : 1 | DIV (arit <: out Instruction a :>, val <: out String v :>) (: arit.code.append(a.code + "\n") .append(" divi " + arit.reg + "," + a.reg + "," + v); :) : 1 | DIV (val <: out String v1 :>, val <: out String v2 :>) (: String temp = nreg(); arit.code.append(" li " + temp + "," + v1 + "\n") .append(" divi " + arit.reg + "," + temp + "," + v2); :) : 1 -- MOD | MOD (arit <: out Instruction a1 :>, arit <: out Instruction a2 :>) (: arit.code.append(a1.code + "\n") .append(a2.code + "\n") .append(" mod " + arit.reg + "," + a1.reg + "," + a2.reg); :) : 1 | MOD (val <: out String v :>, arit <: out Instruction a :>) (: arit.code.append(a.code + "\n") .append(" modi " + arit.reg + "," + a.reg + "," + v); :) : 1 | MOD (arit <: out Instruction a :>, val <: out String v :>) (: arit.code.append(a.code + "\n") .append(" modi " + arit.reg + "," + a.reg + "," + v); :) : 1 | MOD (val <: out String v1 :>, val <: out String v2 :>) (: String temp = nreg(); arit.code.append(" li " + temp + "," + v1 + "\n") .append(" modi " + arit.reg + "," + temp + "," + v2); :) : 1 . end