diff --git a/.cm/SKEL/main.sml b/.cm/SKEL/main.sml index a4435b7..a642803 100644 --- a/.cm/SKEL/main.sml +++ b/.cm/SKEL/main.sml @@ -1,2 +1,2 @@ Skeleton 5 -d2f9d"Flow"d"List"d"Temp"d"Assem"Cd"Canon"d"Parse"d"TextIO"d"MIPSGen"d"MakeGraph"Nad"Main"h3aä¢F"gp1d"MIPSFrame"aä¢Tr"jgp1’gp1e"Translate"ad"S"jgp1’1gp1e"Semant" \ No newline at end of file +d2f7d"Flow"d"List"Cd"Temp"d"Assem"d"Canon"d"Parse"d"TextIO"Cd"MIPSGen"d"Liveness"d"MakeGraph"d"Printtree"d"PrintAbsyn"Nad"Main"h3aä¢F"gp1d"MIPSFrame"aä¢Tr"jgp1’‚gp1e"Translate"ad"S"jgp1’‚gp1e"Semant" \ No newline at end of file diff --git a/.cm/amd64-unix/main.sml b/.cm/amd64-unix/main.sml index e3242a0..0521e8f 100644 Binary files a/.cm/amd64-unix/main.sml and b/.cm/amd64-unix/main.sml differ diff --git a/IR/.cm/amd64-unix/temp.sig b/IR/.cm/amd64-unix/temp.sig index 35fa2f3..afd85aa 100644 Binary files a/IR/.cm/amd64-unix/temp.sig and b/IR/.cm/amd64-unix/temp.sig differ diff --git a/IR/.cm/amd64-unix/temp.sml b/IR/.cm/amd64-unix/temp.sml index 4c7cb2f..41e96ef 100644 Binary files a/IR/.cm/amd64-unix/temp.sml and b/IR/.cm/amd64-unix/temp.sml differ diff --git a/IR/.cm/amd64-unix/translate.sig b/IR/.cm/amd64-unix/translate.sig index d26fd8d..b33f5cc 100644 Binary files a/IR/.cm/amd64-unix/translate.sig and b/IR/.cm/amd64-unix/translate.sig differ diff --git a/IR/.cm/amd64-unix/translate.sml b/IR/.cm/amd64-unix/translate.sml index 1c78fd4..8a92693 100644 Binary files a/IR/.cm/amd64-unix/translate.sml and b/IR/.cm/amd64-unix/translate.sml differ diff --git a/IR/temp.sig b/IR/temp.sig index 544f085..a00606b 100644 --- a/IR/temp.sig +++ b/IR/temp.sig @@ -10,5 +10,7 @@ sig val namedlabel : string -> label structure Set : ORD_SET sharing type Set.Key.ord_key = temp structure Map : ORD_MAP sharing type Map.Key.ord_key = temp + type set = Set.set + val tempSetToString : set -> string end diff --git a/IR/temp.sml b/IR/temp.sml index ec375f3..6c44813 100644 --- a/IR/temp.sml +++ b/IR/temp.sml @@ -3,10 +3,10 @@ struct type temp = int val labelCount = ref 0 - val temps = ref 100 + val temps = ref 0 fun reset () = - let val () = temps := 100 + let val () = temps := 0 val () = labelCount := 0 in () @@ -32,6 +32,12 @@ struct structure Set = SplaySetFn(TempOrd) structure Map = SplayMapFn(TempOrd) + + type 'a map = 'a Map.map + type set = Set.set + + fun tempSetToString (ts) = + (Set.foldl (fn (item, s) => s ^ ", " ^ (makestring item)) "" ts) fun newlabel() = let diff --git a/IR/translate.sml b/IR/translate.sml index 2a66cc3..ebf56f5 100644 --- a/IR/translate.sml +++ b/IR/translate.sml @@ -234,6 +234,7 @@ struct val trBody = unNx body' val trBody' = F.procEntryExit1(levelFrame, trBody) in (* Append to frag list *) + print "procedureEntryExit just added to fragList\n"; fragList := F.PROC ({body = trBody', frame = levelFrame}) :: (!fragList) end diff --git a/assem/.cm/amd64-unix/assem.sml b/assem/.cm/amd64-unix/assem.sml index 00bf486..8d03043 100644 Binary files a/assem/.cm/amd64-unix/assem.sml and b/assem/.cm/amd64-unix/assem.sml differ diff --git a/assem/.cm/amd64-unix/canon.sml b/assem/.cm/amd64-unix/canon.sml index 94c1da4..471f302 100644 Binary files a/assem/.cm/amd64-unix/canon.sml and b/assem/.cm/amd64-unix/canon.sml differ diff --git a/assem/.cm/amd64-unix/codegen.sig b/assem/.cm/amd64-unix/codegen.sig index 916093e..4b1d3b0 100644 Binary files a/assem/.cm/amd64-unix/codegen.sig and b/assem/.cm/amd64-unix/codegen.sig differ diff --git a/assem/.cm/amd64-unix/frame.sig b/assem/.cm/amd64-unix/frame.sig index a517f76..bba30d1 100644 Binary files a/assem/.cm/amd64-unix/frame.sig and b/assem/.cm/amd64-unix/frame.sig differ diff --git a/liveness/.cm/SKEL/flow.sml b/liveness/.cm/SKEL/flow.sml index 4e6d949..a23f640 100644 --- a/liveness/.cm/SKEL/flow.sml +++ b/liveness/.cm/SKEL/flow.sml @@ -1,2 +1,2 @@ Skeleton 5 -d2f2d"Int"d"Temp"ad"Flow"h2ad"G"jgp1d"NodeKey"gp1e"FuncGraph"ad"T"jh0gp1e"IntMapTable" \ No newline at end of file +d2f4d"Int"d"Char"d"Temp"d"String"ad"Flow"h2ad"G"jgp1d"NodeKey"gp1e"FuncGraph"ad"T"jh0gp1e"IntMapTable" \ No newline at end of file diff --git a/liveness/.cm/SKEL/liveness.sml b/liveness/.cm/SKEL/liveness.sml index ec62d64..c247ef1 100644 --- a/liveness/.cm/SKEL/liveness.sml +++ b/liveness/.cm/SKEL/liveness.sml @@ -1,2 +1,3 @@ Skeleton 5 -d3f2d"Flow"d"Temp"ać¢LIVENESS"h0ad"Liveness"jh1ad"G"jgp1d"NodeKey"gp1e"FuncGraph"gp1’ \ No newline at end of file +d2f4d"Int"ä¢Flow"d"List"ä¢Temp"ad"Liveness"h3ad"TempSet"gp2’d"Set"ad"TempMap"gp2’d"Map"aä¢G"gp2’ +’ \ No newline at end of file diff --git a/liveness/.cm/amd64-unix/flow.sml b/liveness/.cm/amd64-unix/flow.sml index aeb7792..efaff08 100644 Binary files a/liveness/.cm/amd64-unix/flow.sml and b/liveness/.cm/amd64-unix/flow.sml differ diff --git a/liveness/.cm/amd64-unix/liveness.sml b/liveness/.cm/amd64-unix/liveness.sml new file mode 100644 index 0000000..441a00c Binary files /dev/null and b/liveness/.cm/amd64-unix/liveness.sml differ diff --git a/liveness/.cm/amd64-unix/makegraph.sml b/liveness/.cm/amd64-unix/makegraph.sml index 877b4be..d1e3b79 100644 Binary files a/liveness/.cm/amd64-unix/makegraph.sml and b/liveness/.cm/amd64-unix/makegraph.sml differ diff --git a/liveness/flow.sml b/liveness/flow.sml index 6291c92..2135440 100644 --- a/liveness/flow.sml +++ b/liveness/flow.sml @@ -3,12 +3,14 @@ struct structure G = FuncGraph (NodeKey) structure T = IntMapTable (type key = int fun getInt(n) = n) - type node = string * Temp.temp list * Temp.temp list * bool * Temp.label list option + type node = string * Temp.temp list * Temp.temp list * (Temp.temp * Temp.temp) option * Temp.label list option type graph = node G.graph - datatype flowgraph = FGRAPH of {control: graph, - def: Temp.temp list T.table, - use: Temp.temp list T.table, - ismove: bool T.table} fun printNode (nid, (assem, def, use, ismove, jump)) = Int.toString nid ^ ": " ^ assem + fun printNodeForVis (nid, (assem, def, use, ismove, jump)) = + Int.toString nid ^ ": " ^ String.translate (fn (c) => (case c of + #"\n" => "|" + | _ => Char.toString c)) (let val format0 = (* Assem.format(Temp.makestring) *) (fn x => x) + in (format0 assem) + end) end \ No newline at end of file diff --git a/liveness/graph/.cm/amd64-unix/funcgraph.sig b/liveness/graph/.cm/amd64-unix/funcgraph.sig index c2748ab..ce0c837 100644 Binary files a/liveness/graph/.cm/amd64-unix/funcgraph.sig and b/liveness/graph/.cm/amd64-unix/funcgraph.sig differ diff --git a/liveness/graph/.cm/amd64-unix/funcgraph.sml b/liveness/graph/.cm/amd64-unix/funcgraph.sml index f55437e..9e9a3d2 100644 Binary files a/liveness/graph/.cm/amd64-unix/funcgraph.sml and b/liveness/graph/.cm/amd64-unix/funcgraph.sml differ diff --git a/liveness/graph/funcgraph.sig b/liveness/graph/funcgraph.sig index 7c9e8c6..6d7ee16 100644 --- a/liveness/graph/funcgraph.sig +++ b/liveness/graph/funcgraph.sig @@ -105,6 +105,8 @@ val isAdjacent: 'a node * 'a node -> bool * that says how to convert any given node's data into a * string, and it will print everything out *) -val printGraph: ((nodeID * 'a) -> string) -> 'a graph -> unit +val printGraph: ((nodeID * 'a) -> string) -> 'a graph -> bool -> unit + +val printGraphVis : ((nodeID * 'a) -> string) -> 'a graph -> unit end diff --git a/liveness/graph/funcgraph.sml b/liveness/graph/funcgraph.sml index 902c1c0..6939080 100644 --- a/liveness/graph/funcgraph.sml +++ b/liveness/graph/funcgraph.sml @@ -113,7 +113,7 @@ struct NodeSet.member(NodeSet.union(s1,p1),n2) orelse NodeSet.member(NodeSet.union(s2,p2),n1) - fun printGraph stringify g = + fun printGraph stringify g printSuccPred = let fun println x = print(x ^"\n") fun stringNid nid = let val (_,data,_,_) = getNode(g,nid) @@ -123,13 +123,38 @@ struct fun prOneNode(nid,data,succs,preds) = let val s = stringify(nid,data) val () = println("Node: " ^ s) - val () = println(" -> Successors:") - val () = prSet succs - val () = println(" -> Predecessors:") - val () = prSet preds + val _ = (if printSuccPred then + (println(" -> Successors:"); + prSet succs; + println(" -> Predecessors:"); + prSet preds) + else ()) in () end in NodeMap.app prOneNode g end + + fun printGraphVis stringify g = + let fun println x = print(x ^"\n") + fun stringNid nid = + let val (_,data,_,_) = getNode(g,nid) + in stringify(nid,data) + end + fun prSet s = NodeSet.app (println o stringNid) s + + fun prNodeName (nid, data, succs, preds) = + let val s = stringify(nid, data) + val _ = println("\"" ^ s ^ "\"") + in () + end + + fun prOneAllSuccs(nid,data,succs,preds) = + let val thisName = stringify(nid,data) + val _ = NodeSet.app ((fn node => (print ("\"" ^ thisName ^ "\" \"" ^ node ^ "\"\n"))) o stringNid) succs + in () + end + in NodeMap.app prNodeName g; + NodeMap.app prOneAllSuccs g + end end diff --git a/liveness/liveness.sml b/liveness/liveness.sml index 838a996..d54c719 100644 --- a/liveness/liveness.sml +++ b/liveness/liveness.sml @@ -1,18 +1,124 @@ -signature LIVENESS = +(* signature LIVENESS = sig type igraph type node + type live + type livegraph (* val interferenceGraph : Flow.flowgraph -> igraph * (node -> Temp.temp list) val show : outstream * igraph -> unit *) -end + val flowToLiveGraph : Flow.graph -> livegraph + val showLiveGraph : livegraph -> unit -structure Liveness : LIVENESS = +end *) + +structure Liveness (*: LIVENESS*) = struct - structure G = FuncGraph (NodeKey) - type igraph = G.graph - type node = Flow.node - datatype igraph = IGRAPH of {graph: igraph, + structure TempSet = Temp.Set + structure TempMap = Temp.Map + structure G = Flow.G + + type temp_set = TempSet.set + + type node = Temp.temp G.node + datatype igraph = IGRAPH of {graph: Temp.temp G.graph, tnode: Temp.temp -> node, gtemp: node -> Temp.temp, moves: (node * node) list} + + + type live = {def: Temp.set, + use: Temp.set, + move: (Temp.temp * Temp.temp) option, + liveIn: Temp.set, + liveOut: Temp.set} + + type livegraph = live G.graph + + (* Calculates liveness and adds that info to flow graph *) + fun flowToLiveGraph (flow : Flow.node G.graph) : livegraph = + let fun convertFlowToLive () = + (* Copy original graph (only nodes) *) + let fun init (flowNode : Flow.node Flow.G.node, liveGraph : livegraph) = + let val nid = G.getNodeID (flowNode) + val (assm, def, use, move, jump) = G.nodeInfo (flowNode) + val newInfo = {def=TempSet.addList (TempSet.empty, def), + use=TempSet.addList (TempSet.empty, use), + move=move, + liveIn=Temp.Set.empty, + liveOut=Temp.Set.empty} + in G.addNode (liveGraph, nid, newInfo) + end + + (* Copy the edges *) + fun copyEdges (oldNode, newGraph) = + let val nid = G.getNodeID (oldNode) + val oldInfo = G.nodeInfo (oldNode) + val oldSuccs = G.succs (oldNode) + val newNode = G.getNode (newGraph, nid) + in List.foldl (fn (succ, graph) => G.addEdge (graph, {from=nid, to=succ})) newGraph oldSuccs + end + + fun iterateLiveness (edgedGraph) = + let fun iterGraph (nid, graph) = + let val node = G.getNode (graph, nid) + + val info = G.nodeInfo node + val {def=def, use=use, move=move, liveIn=oldLiveIn, liveOut=oldLiveOut} = info + + val succs = G.succs (node) + val preds = G.preds (node) + + val newLiveIn = TempSet.union (use, (TempSet.difference (oldLiveOut, def))) + val newLiveOut = foldl (fn (nid, set) => let val iterNode = G.getNode (graph, nid) + val lIn = #liveIn (G.nodeInfo iterNode) + in TempSet.union (set, lIn) + end) TempSet.empty succs + val unchanged : bool = ((TempSet.equal (oldLiveIn, newLiveIn)) andalso (TempSet.equal (oldLiveOut, newLiveOut))) + val newInfo = {def=def, use=use, move=move, liveIn=newLiveIn, liveOut=newLiveOut} + val newGraph = G.changeNodeData (graph, nid, newInfo) + in (unchanged, newGraph) + end + + fun untilUnchanged (true, graph) = graph + | untilUnchanged (false, graph) = + untilUnchanged (G.foldNodes (fn (node, (unchanged, graph)) => + (let val nid = G.getNodeID(node) + val (newUnchanged, newGraph) = iterGraph (nid, graph) + in (unchanged andalso newUnchanged, newGraph) + end )) (true, graph) graph) + in untilUnchanged (false, edgedGraph) + end + + val initializedGraph : livegraph = G.foldNodes init G.empty flow + val edgedGraph : livegraph = G.foldNodes copyEdges initializedGraph flow + val liveGraph : livegraph = iterateLiveness edgedGraph + + in liveGraph + end + in convertFlowToLive () + end + + (* Uses a flow graph with liveness info to make an interference graph *) + (* fun interferenceGraph (flow) = let val liveGraph = flowToLiveGraph flow + in {graph=graph, + tnode=tnode, + gtemp=gtemp, + moves=moves} + end *) + + fun moveToString (SOME (t1, t2)) = (Temp.makestring t1 ^ " <- " ^ Temp.makestring t2) + | moveToString (NONE) = "N/A" + + fun showLiveGraph (liveGraph : livegraph) = + (print "\n--- Live Graph: --- \n"; + G.printGraph (fn (nid, liveObj:live) => + let val liveIn : Temp.set = #liveIn liveObj + val liveOut : Temp.set = #liveOut liveObj + val move = #move liveObj + in ("nid = " ^ (Int.toString nid) ^ " \tliveIn: " ^ (Temp.tempSetToString liveIn) ^ + " \tliveOut: " ^ (Temp.tempSetToString liveOut) ^ + " \tmove: " ^ (moveToString move)) + end) liveGraph false) + + end \ No newline at end of file diff --git a/liveness/makegraph.sml b/liveness/makegraph.sml index 79f9c8d..bc0d9e2 100644 --- a/liveness/makegraph.sml +++ b/liveness/makegraph.sml @@ -19,9 +19,9 @@ struct (* Converts an instruction to one node Returns: a node *) - fun makenode (A.OPER {assem, dst, src, jump}) = (assem, dst, src, false, jump) - | makenode (A.LABEL {assem, lab}) = (assem, [], [], false, NONE) - | makenode (A.MOVE {assem, dst, src}) = (assem, [dst], [src], true, NONE) + fun makenode (A.OPER {assem, dst, src, jump}) = (assem, dst, src, NONE, jump) + | makenode (A.LABEL {assem, lab}) = (assem, [], [], NONE, NONE) + | makenode (A.MOVE {assem, dst, src}) = (assem, [dst], [src], SOME(dst, src), NONE) (* Adds all of the instructions as nodes to the graph @@ -45,12 +45,11 @@ struct val nodeValue = case nodeOption of SOME (nodeVal) => nodeVal | NONE => (Err.error 0 ("name = " ^ Symbol.name lbl); raise NoneJump ("name = " ^ Symbol.name lbl)) - in G.addEdge (graph, {from=G.getNodeID (node), - to=G.getNodeID (valOf (S.look (labelmap, lbl)))}) + in G.addEdge (graph, {from=G.getNodeID (node), + to=G.getNodeID nodeValue}) end) graph jumps - (* Adds edges to the control flow graph Returns: graph *) @@ -60,7 +59,7 @@ struct in (case jump of NONE => addedges (addnextedge (graph, node, prev), labelmap, nodes, SOME (node)) - | SOME (jumps) => addedges (addnextedge (addjumps (graph, labelmap, node, jumps), node, prev), labelmap, nodes, SOME(node))) + | SOME (jumps) => addedges (addnextedge (addjumps (graph, labelmap, node, jumps), node, prev), labelmap, nodes, NONE)) end fun instrs2graph (instrs) = let val (nodeGraph, labelmap) = addnodes (G.empty, instrs, S.empty, 0) diff --git a/main.sml b/main.sml index 4f1b115..1a3e088 100644 --- a/main.sml +++ b/main.sml @@ -8,32 +8,52 @@ struct fun emitproc out (F.PROC{body,frame}) = let val _ = print ("emit " ^ F.name frame ^ "\n") + (* Linearize the statements of the body and trace schedule *) (* val _ = Printtree.printtree(out,body); *) val stms = Canon.linearize body - (* val _ = app (fn s => Printtree.printtree(out,s)) stms; *) + val _ = app (fn s => Printtree.printtree(TextIO.stdOut,s)) stms; val stms' = Canon.traceSchedule(Canon.basicBlocks stms) + + (* Convert to list of instructions *) val instrs = F.procEntryExit2 (frame, List.concat (map (MIPSGen.codeGen frame) stms')) val {prolog, body, epilog} = F.procEntryExit3 (frame, instrs) - val (graph, nodelist) = MakeGraph.instrs2graph (body) - val printgraph = Flow.G.printGraph (Flow.printNode) - val _ = printgraph graph + (* Format those instructions using temp names *) val format0 = Assem.format(Temp.makestring) + + (* Make a flow graph *) + val (graph, nodelist) = MakeGraph.instrs2graph (body) + val _ = (print "\n--- Control Flow Graph: ---\n") + val _ = Flow.G.printGraph (Flow.printNode) graph true + + (* Print the ready-to-plot flow graph *) + val _ = print "\n--- CFG for usage in https://csacademy.com/app/graph_editor/ : ---\n" + val _ = Flow.G.printGraphVis (Flow.printNodeForVis) graph + + (* Convert to a liveGraph *) + val liveGraph : Liveness.livegraph = Liveness.flowToLiveGraph graph + val _ = Liveness.showLiveGraph liveGraph + + (* Convert to an interference graph *) + (* TODO *) in (TextIO.output (out, prolog); (app (fn i => TextIO.output(out, (format0 i) ^ "\n")) instrs); TextIO.output (out, epilog)) end | emitproc out (F.STRING(lab,s)) = TextIO.output(out, (F.string (lab,s)) ^ "\n") fun withOpenFile fname f = let val out = TextIO.openOut fname - in ((f TextIO.stdOut); (f out before TextIO.closeOut out)) + in ((*(f TextIO.stdOut);*) (f out before TextIO.closeOut out)) handle e => (TextIO.closeOut out; raise e) end fun compile filename = - let val absyn = Parse.parse (filename ^ ".tig") + let val absyn = Parse.parse (filename ^ ".tig") + val _ = print "\nAbstract Syntax Tree: \n"; + val _ = PrintAbsyn.print (TextIO.stdOut, absyn) + val _ = Temp.reset () val frags = ((*FindEscape.prog absyn;*) S.transProg absyn) in withOpenFile (filename ^ ".s") - (fn out => (app (emitproc out) frags)) + (fn out => (app (emitproc out) (List.rev frags))) end end \ No newline at end of file diff --git a/mips/.cm/amd64-unix/mipsframe.sml b/mips/.cm/amd64-unix/mipsframe.sml index af0fc62..0b2ffa2 100644 Binary files a/mips/.cm/amd64-unix/mipsframe.sml and b/mips/.cm/amd64-unix/mipsframe.sml differ diff --git a/mips/.cm/amd64-unix/mipsgen.sml b/mips/.cm/amd64-unix/mipsgen.sml index a3ca3d8..341f10b 100644 Binary files a/mips/.cm/amd64-unix/mipsgen.sml and b/mips/.cm/amd64-unix/mipsgen.sml differ diff --git a/mips/mipsframe.sml b/mips/mipsframe.sml index 6d6e301..301831c 100644 --- a/mips/mipsframe.sml +++ b/mips/mipsframe.sml @@ -114,14 +114,16 @@ struct fun procEntryExit1(frame', stm') = stm' + (* TODO: add the sink back (see page 208) *) fun procEntryExit2(frame, body) = - body @ + body + (* body @ [A.OPER{assem="", src =[ZERO,RA,SP]@calleesaves, - dst=[], jump=SOME[]}] + dst=[], jump=SOME[]}] *) fun procEntryExit3({name, formals, numLocals, curOffset}, body) = - {prolog = "PROCEDURE " ^ Symbol.name name ^ "\n", + {prolog = "PROCEDURE " ^ Symbol.name name ^ "\n" ^ Symbol.name name ^ ": \n", body = body, epilog = "END " ^ Symbol.name name ^ "\n"} diff --git a/mips/mipsgen.sml b/mips/mipsgen.sml index cd5d872..aed933b 100644 --- a/mips/mipsgen.sml +++ b/mips/mipsgen.sml @@ -29,11 +29,11 @@ struct (* (e1 + i) <-- e2 *) | munchStm(T.MOVE(T.MEM(T.BINOP(T.PLUS,e1,T.CONST i)),e2)) = emit(A.OPER{assem="sw `s0, " ^ Int.toString i ^ "(`s1)", - src=[munchExp e1, munchExp e2], + src=[munchExp e2, munchExp e1], dst=[],jump=NONE}) | munchStm(T.MOVE(T.MEM(T.BINOP(T.PLUS,T.CONST i,e1)),e2)) = emit(A.OPER{assem="sw `s0, " ^ Int.toString i ^ "(`s1)", - src=[munchExp e1, munchExp e2], + src=[munchExp e2, munchExp e1], dst=[],jump=NONE}) (* (e1 - i) <-- e2 *) @@ -50,7 +50,7 @@ struct (* (i) <-- e2 *) | munchStm(T.MOVE(T.MEM(e1), e2)) = emit(A.OPER{assem="sw `s0, 0(`s1)", - src=[munchExp e1, munchExp e2], + src=[munchExp e2, munchExp e1], dst= [] ,jump=NONE}) @@ -101,7 +101,7 @@ struct (* Branches *) | munchStm (T.JUMP(T.NAME lab, _)) = - emit(A.OPER{assem="jr `j0",src=[],dst=[],jump=SOME([lab])}) + emit(A.OPER{assem="j `j0",src=[],dst=[],jump=SOME([lab])}) | munchStm (T.JUMP(e, labels)) = emit(A.OPER{assem="jr `j0",src=[munchExp e], @@ -300,6 +300,49 @@ struct result(fn r => emit(A.OPER{assem="xor `d0, `s0, `s1", src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + (* Relational Operations *) + + | munchExp (T.RELOP (T.GE, e1, e2)) = + result(fn r => emit(A.OPER{assem="sge `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.UGE, e1, e2)) = + result(fn r => emit(A.OPER{assem="sgeu `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.GT, e1, e2)) = + result(fn r => emit(A.OPER{assem="sgt `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.UGT, e1, e2)) = + result(fn r => emit(A.OPER{assem="sgtu `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.LT, e1, e2)) = + result(fn r => emit(A.OPER{assem="slt `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.ULT, e1, e2)) = + result(fn r => emit(A.OPER{assem="sltu `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.LE, e1, e2)) = + result(fn r => emit(A.OPER{assem="sle `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.ULE, e1, e2)) = + result(fn r => emit(A.OPER{assem="sleu `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.EQ, e1, e2)) = + result(fn r => emit(A.OPER{assem="seq `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + | munchExp (T.RELOP (T.NE, e1, e2)) = + result(fn r => emit(A.OPER{assem="sne `d0, `s0, `s1", + src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + (* Shifts *) | munchExp(T.BINOP(T.LSHIFT,e1,T.CONST i)) = result(fn r => emit(A.OPER{assem="sll `d0, `s0 " ^ Int.toString i, @@ -329,6 +372,8 @@ struct result(fn r => emit(A.OPER{assem="srav `d0, `s0, `s1", src=[munchExp e1, munchExp e2], dst=[r], jump=NONE})) + + (* Registers *) | munchExp(T.TEMP t) = t diff --git a/parser/.cm/amd64-unix/tiger.grm.sml b/parser/.cm/amd64-unix/tiger.grm.sml index 3b01ebe..954b910 100644 Binary files a/parser/.cm/amd64-unix/tiger.grm.sml and b/parser/.cm/amd64-unix/tiger.grm.sml differ diff --git a/parser/tiger.grm b/parser/tiger.grm index 49277bc..afce725 100644 --- a/parser/tiger.grm +++ b/parser/tiger.grm @@ -62,6 +62,8 @@ fun a_IGNORE_ME x = 3; %nonassoc EQ NEQ LT LE GT GE +%left SEMICOLON + %left PLUS MINUS %left TIMES DIVIDE @@ -228,7 +230,7 @@ exp: | IF exp THEN exp %prec DO (A.IfExp({test=exp1, then'=exp2, else'=NONE, pos=IFleft})) (* Loops *) - | WHILE exp DO exp (A.WhileExp({test=exp1, body=exp, pos=WHILEleft})) + | WHILE exp DO exp (A.WhileExp({test=exp1, body=exp2, pos=WHILEleft})) | FOR ID ASSIGN exp TO exp DO exp (A.ForExp({var=Symbol.symbol ID, escape=(ref true), lo=exp1, hi=exp2, body=exp3, pos=FORleft})) | BREAK (A.BreakExp(BREAKleft)) @@ -249,7 +251,7 @@ exp: | exp GT exp (A.OpExp({left=exp1, oper=A.GtOp, right=exp2, pos=exp1left})) (* Expression sequence *) - | exp exp_tail (A.SeqExp((exp, expleft)::exp_tail)) + | exp exp_tail (A.SeqExp((exp, expleft)::exp_tail)) (* Allow dealing with sequences of expressions, such as in the first body diff --git a/parser/tiger.grm.desc b/parser/tiger.grm.desc index 01faec1..9c5f1e4 100644 --- a/parser/tiger.grm.desc +++ b/parser/tiger.grm.desc @@ -1,24 +1,10 @@ 27 reduce/reduce conflicts -47 shift/reduce conflicts +28 shift/reduce conflicts 1 rule not reduced warning: rule will never be reduced error: state 32: shift/reduce conflict (shift FUNCTION, reduce by rule 5) error: state 35: shift/reduce conflict (shift TYPE, reduce by rule 4) -error: state 45: shift/reduce conflict (shift SEMICOLON, reduce by rule 40) -error: state 52: shift/reduce conflict (shift SEMICOLON, reduce by rule 50) -error: state 54: shift/reduce conflict (shift SEMICOLON, reduce by rule 58) -error: state 55: shift/reduce conflict (shift SEMICOLON, reduce by rule 57) -error: state 56: shift/reduce conflict (shift SEMICOLON, reduce by rule 62) -error: state 57: shift/reduce conflict (shift SEMICOLON, reduce by rule 64) -error: state 58: shift/reduce conflict (shift SEMICOLON, reduce by rule 61) -error: state 59: shift/reduce conflict (shift SEMICOLON, reduce by rule 63) -error: state 60: shift/reduce conflict (shift SEMICOLON, reduce by rule 60) -error: state 61: shift/reduce conflict (shift SEMICOLON, reduce by rule 59) -error: state 62: shift/reduce conflict (shift SEMICOLON, reduce by rule 43) -error: state 63: shift/reduce conflict (shift SEMICOLON, reduce by rule 44) -error: state 64: shift/reduce conflict (shift SEMICOLON, reduce by rule 42) -error: state 65: shift/reduce conflict (shift SEMICOLON, reduce by rule 41) error: state 66: shift/reduce conflict (shift OR, reduce by rule 68) error: state 66: shift/reduce conflict (shift AND, reduce by rule 68) error: state 66: shift/reduce conflict (shift GE, reduce by rule 68) @@ -32,8 +18,6 @@ error: state 66: shift/reduce conflict (shift TIMES, reduce by rule 68) error: state 66: shift/reduce conflict (shift MINUS, reduce by rule 68) error: state 66: shift/reduce conflict (shift PLUS, reduce by rule 68) error: state 66: shift/reduce conflict (shift SEMICOLON, reduce by rule 68) -error: state 92: shift/reduce conflict (shift SEMICOLON, reduce by rule 53) -error: state 93: shift/reduce conflict (shift SEMICOLON, reduce by rule 52) error: state 101: shift/reduce conflict (shift OR, reduce by rule 68) error: state 101: shift/reduce conflict (shift AND, reduce by rule 68) error: state 101: shift/reduce conflict (shift GE, reduce by rule 68) @@ -74,9 +58,6 @@ error: state 119: reduce/reduce conflict between rule 67 and rule 66 on RPAREN error: state 119: reduce/reduce conflict between rule 67 and rule 66 on SEMICOLON error: state 119: reduce/reduce conflict between rule 67 and rule 66 on COMMA error: state 119: reduce/reduce conflict between rule 67 and rule 66 on EOF -error: state 128: shift/reduce conflict (shift SEMICOLON, reduce by rule 51) -error: state 130: shift/reduce conflict (shift SEMICOLON, reduce by rule 49) -error: state 143: shift/reduce conflict (shift SEMICOLON, reduce by rule 54) state 0: @@ -959,7 +940,6 @@ state 44: . error -error: state 45: shift/reduce conflict (shift SEMICOLON, reduce by rule 40) state 45: @@ -978,7 +958,6 @@ state 45: exp : exp . GT exp exp : exp . exp_tail - SEMICOLON shift 31 exp_tail goto 18 @@ -1126,7 +1105,6 @@ state 51: . error -error: state 52: shift/reduce conflict (shift SEMICOLON, reduce by rule 50) state 52: @@ -1172,7 +1150,6 @@ state 53: . reduce by rule 25 -error: state 54: shift/reduce conflict (shift SEMICOLON, reduce by rule 58) state 54: @@ -1207,7 +1184,6 @@ state 54: . reduce by rule 58 -error: state 55: shift/reduce conflict (shift SEMICOLON, reduce by rule 57) state 55: @@ -1242,7 +1218,6 @@ state 55: . reduce by rule 57 -error: state 56: shift/reduce conflict (shift SEMICOLON, reduce by rule 62) state 56: @@ -1287,7 +1262,6 @@ state 56: . error -error: state 57: shift/reduce conflict (shift SEMICOLON, reduce by rule 64) state 57: @@ -1332,7 +1306,6 @@ state 57: . error -error: state 58: shift/reduce conflict (shift SEMICOLON, reduce by rule 61) state 58: @@ -1377,7 +1350,6 @@ state 58: . error -error: state 59: shift/reduce conflict (shift SEMICOLON, reduce by rule 63) state 59: @@ -1422,7 +1394,6 @@ state 59: . error -error: state 60: shift/reduce conflict (shift SEMICOLON, reduce by rule 60) state 60: @@ -1467,7 +1438,6 @@ state 60: . error -error: state 61: shift/reduce conflict (shift SEMICOLON, reduce by rule 59) state 61: @@ -1512,7 +1482,6 @@ state 61: . error -error: state 62: shift/reduce conflict (shift SEMICOLON, reduce by rule 43) state 62: @@ -1531,13 +1500,11 @@ state 62: exp : exp . GT exp exp : exp . exp_tail - SEMICOLON shift 31 exp_tail goto 18 . reduce by rule 43 -error: state 63: shift/reduce conflict (shift SEMICOLON, reduce by rule 44) state 63: @@ -1556,13 +1523,11 @@ state 63: exp : exp . GT exp exp : exp . exp_tail - SEMICOLON shift 31 exp_tail goto 18 . reduce by rule 44 -error: state 64: shift/reduce conflict (shift SEMICOLON, reduce by rule 42) state 64: @@ -1581,7 +1546,6 @@ state 64: exp : exp . GT exp exp : exp . exp_tail - SEMICOLON shift 31 TIMES shift 28 DIVIDE shift 27 @@ -1589,7 +1553,6 @@ state 64: . reduce by rule 42 -error: state 65: shift/reduce conflict (shift SEMICOLON, reduce by rule 41) state 65: @@ -1608,7 +1571,6 @@ state 65: exp : exp . GT exp exp : exp . exp_tail - SEMICOLON shift 31 TIMES shift 28 DIVIDE shift 27 @@ -2110,7 +2072,6 @@ state 91: . error -error: state 92: shift/reduce conflict (shift SEMICOLON, reduce by rule 53) state 92: @@ -2147,7 +2108,6 @@ state 92: . reduce by rule 53 -error: state 93: shift/reduce conflict (shift SEMICOLON, reduce by rule 52) state 93: @@ -2809,7 +2769,6 @@ state 127: . error -error: state 128: shift/reduce conflict (shift SEMICOLON, reduce by rule 51) state 128: @@ -2855,7 +2814,6 @@ state 129: . reduce by rule 34 -error: state 130: shift/reduce conflict (shift SEMICOLON, reduce by rule 49) state 130: @@ -3086,7 +3044,6 @@ state 142: . reduce by rule 16 -error: state 143: shift/reduce conflict (shift SEMICOLON, reduce by rule 54) state 143: @@ -3191,5 +3148,5 @@ state 146: . error -619 of 1174 action table entries left after compaction +614 of 1169 action table entries left after compaction 182 goto table entries diff --git a/parser/tiger.grm.sml b/parser/tiger.grm.sml index 8bd045f..2b57680 100644 --- a/parser/tiger.grm.sml +++ b/parser/tiger.grm.sml @@ -213,11 +213,11 @@ val table=let val actionRows = \\186\000\000\000\ \\187\000\000\000\ \\188\000\000\000\ -\\189\000\007\000\033\000\000\000\ -\\190\000\007\000\033\000\018\000\030\000\019\000\029\000\000\000\ -\\191\000\007\000\033\000\018\000\030\000\019\000\029\000\000\000\ -\\192\000\007\000\033\000\000\000\ -\\193\000\007\000\033\000\000\000\ +\\189\000\000\000\ +\\190\000\018\000\030\000\019\000\029\000\000\000\ +\\191\000\018\000\030\000\019\000\029\000\000\000\ +\\192\000\000\000\ +\\193\000\000\000\ \\194\000\000\000\ \\195\000\000\000\ \\196\000\000\000\ @@ -1079,10 +1079,10 @@ end) end | ( 53, ( ( _, ( MlyValue.exp exp2, _, exp2right)) :: _ :: ( _, ( MlyValue.exp exp1, _, _)) :: ( _, ( _, (WHILEleft as WHILE1left), _)) - :: rest671)) => let val result = MlyValue.exp (fn _ => let val (exp - as exp1) = exp1 () + :: rest671)) => let val result = MlyValue.exp (fn _ => let val exp1 + = exp1 () val exp2 = exp2 () - in (A.WhileExp({test=exp1, body=exp, pos=WHILEleft})) + in (A.WhileExp({test=exp1, body=exp2, pos=WHILEleft})) end) in ( LrTable.NT 1, ( result, WHILE1left, exp2right), rest671) end diff --git a/semant/.cm/amd64-unix/env.sig b/semant/.cm/amd64-unix/env.sig index 34c9318..8c04c34 100644 Binary files a/semant/.cm/amd64-unix/env.sig and b/semant/.cm/amd64-unix/env.sig differ diff --git a/semant/.cm/amd64-unix/env.sml b/semant/.cm/amd64-unix/env.sml index 6b987c9..8da3afe 100644 Binary files a/semant/.cm/amd64-unix/env.sml and b/semant/.cm/amd64-unix/env.sml differ diff --git a/semant/.cm/amd64-unix/semant.sml b/semant/.cm/amd64-unix/semant.sml index 59b5520..b8ebe5c 100644 Binary files a/semant/.cm/amd64-unix/semant.sml and b/semant/.cm/amd64-unix/semant.sml differ diff --git a/sources.cm b/sources.cm index f371406..99b0979 100644 --- a/sources.cm +++ b/sources.cm @@ -21,30 +21,30 @@ Group is parser/parse.sml (* Semantic Analysis *) + absyn/types.sml + table/table.sig table/table.sml table/symbol.sml - (* IR *) - - tree/tree.sml - tree/printtree.sml - - ir/translate.sig - ir/translate.sml + semant/env.sig + semant/env.sml semant/semant.sig semant/semant.sml - - absyn/types.sml - - semant/env.sig - semant/env.sml + + (* IR *) + tree/tree.sml + tree/printtree.sml ir/temp.sig ir/temp.sml + ir/translate.sig + ir/translate.sml + + (* Instruction Selection *) assem/frame.sig mips/mipsframe.sml @@ -54,10 +54,11 @@ Group is assem/canon.sml assem/assem.sml + (* Liveness Analysis *) liveness/graph/funcgraph.sig liveness/graph/funcgraph.sml liveness/flow.sml liveness/nodekey.sml liveness/makegraph.sml - (* liveness/liveness.sml *) \ No newline at end of file + liveness/liveness.sml \ No newline at end of file diff --git a/testcases/test1.s b/testcases/test1.s index e1ae4dd..337d849 100644 --- a/testcases/test1.s +++ b/testcases/test1.s @@ -1,9 +1,9 @@ -PROCEDURE L0 -L5: +PROCEDURE L22 +L27: MISSING EXP -sw t124, ~4(t132) -lw t133, ~4(t124) -jr L4 -L4: +sw t124, ~4(t170) +lw t171, ~4(t124) +jr L26 +L26: -END L0 +END L22 diff --git a/testcases/test10.s b/testcases/test10.s new file mode 100644 index 0000000..0ab3fbb --- /dev/null +++ b/testcases/test10.s @@ -0,0 +1,16 @@ +PROCEDURE L0 +L2: +addi t30, r0, 1 +addi t32, r0, 10 +addi t33, r0, 5 +sgt t31, t32, t33 +beq t30, t31, L3 +b L1 +L1: +j L4 +L3: +addi t35, r0, 5 +addi t34, t35, 6 +j L2 +L4: +END L0 diff --git a/testcases/test10.tig b/testcases/test10.tig index d4038d7..4c11cd8 100644 --- a/testcases/test10.tig +++ b/testcases/test10.tig @@ -1,2 +1,2 @@ /* error : body of while not unit */ -while(10 > 5) do 5+6 +while(10 > 5) do 5+6; nil diff --git a/testcases/test36.s b/testcases/test36.s new file mode 100644 index 0000000..e69de29 diff --git a/testcases/test37.s b/testcases/test37.s index 1d6b9fb..a252f65 100644 --- a/testcases/test37.s +++ b/testcases/test37.s @@ -1,13 +1,7 @@ -PROCEDURE L0 -L4: -addi t135, r0, 0 -sw t124, ~4(t135) -addi t136, r0, 1 -sw t124, ~8(t136) -lw t138, ~4(t124) -lw t139, ~8(t124) -add t137, t138, t139 -jr L3 +PROCEDURE L1 +L1: L3: - -END L0 +add t3, t1, t2 +j L2 +L2: +END L1 diff --git a/testcases/test37.tig b/testcases/test37.tig index 2f37c63..a4eb8a4 100644 --- a/testcases/test37.tig +++ b/testcases/test37.tig @@ -1,8 +1,12 @@ /* redeclaration of variable; this is legal, there are two different variables with the same name. The second one hides the first. */ let - var a := 0 - var b := 1 + var a := 7 + var b := 9 + var c := 3 + + function add(a : int, b : int) : int = + a + b in - a + b + c := add(a, b) end diff --git a/testcases/test4.s b/testcases/test4.s index 584763b..e69de29 100644 --- a/testcases/test4.s +++ b/testcases/test4.s @@ -1,58 +0,0 @@ -L11: -move t156, t106 -move t157, t107 -move t158, t108 -move t159, t109 -move t160, t110 -move t161, t111 -move t162, t112 -move t163, t113 -move t102, t124 -addi t164, r0, 10 -move t103, t164 -jal L1 -move t113, t163 -move t112, t162 -move t111, t161 -move t110, t160 -move t109, t159 -move t108, t158 -move t107, t157 -move t106, t156 -jr L10 -L10: -L13: -addi t167, r0, 1 -MISSING EXP -beq t167, t168, L2 -b L3 -L3: -move t166, t131 -move t169, t106 -move t170, t107 -move t171, t108 -move t172, t109 -move t173, t110 -move t174, t111 -move t175, t112 -move t176, t113 -move t102, t124 -addi t178, r0, 1 -sub t177, t131, t178 -move t103, t177 -jal L1 -move t113, t176 -move t112, t175 -move t111, t174 -move t110, t173 -move t109, t172 -move t108, t171 -move t107, t170 -move t106, t169 -move t165, t125 -mul t179, t166, t165 -L4: -jr L12 -L2: -jr L4 -L12: diff --git a/testcases/test8.s b/testcases/test8.s new file mode 100644 index 0000000..5dca87f --- /dev/null +++ b/testcases/test8.s @@ -0,0 +1,14 @@ +PROCEDURE L0 +L8: +addi t132, r0, 1 +MISSING EXP +beq t132, t133, L1 +b L2 +L2: +L3: +jr L7 +L1: +jr L3 +L7: + +END L0 diff --git a/testcases/test9.s b/testcases/test9.s new file mode 100644 index 0000000..a0e77d5 --- /dev/null +++ b/testcases/test9.s @@ -0,0 +1,15 @@ +PROCEDURE L3 +L9: +addi t36, r0, 1 +MISSING EXP +beq t36, t37, L5 +b L6 +L6: +la t38, L4 +L7: +jr L8 +L5: +jr L7 +L8: +END L3 + diff --git a/tree/.cm/amd64-unix/printtree.sml b/tree/.cm/amd64-unix/printtree.sml index 221cb10..d3be874 100644 Binary files a/tree/.cm/amd64-unix/printtree.sml and b/tree/.cm/amd64-unix/printtree.sml differ diff --git a/tree/.cm/amd64-unix/tree.sml b/tree/.cm/amd64-unix/tree.sml index 2accb5f..f37b937 100644 Binary files a/tree/.cm/amd64-unix/tree.sml and b/tree/.cm/amd64-unix/tree.sml differ