diff -r 36379b038438 -r e83afb44f276 progs/fun_llvm.scala --- a/progs/fun_llvm.scala Mon Oct 07 20:53:25 2019 +0100 +++ b/progs/fun_llvm.scala Tue Oct 08 21:12:52 2019 +0100 @@ -15,7 +15,7 @@ -//object Compiler { +object Compiler { import java.io._ import scala.util._ @@ -60,7 +60,10 @@ case class KVar(s: String) extends KExp case class KNum(i: Int) extends KExp case class KAop(o: String, x1: String, x2: String) extends KExp -case class KIfeq(x1: String, x2: String, e1: KExp, e2: KExp) extends KExp +case class KIfeq(x1: String, x2: String, e1: KExp, e2: KExp) extends KExp { + override def toString = s"KIf $x1 == $x2 \nIF\n$e1\nELSE\n$e2" + +} case class KCall(o: String, vrs: List[String]) extends KExp case class KLet(x: String, e1: KExp, e2: KExp) extends KExp { override def toString = s"let $x = $e1 in \n$e2" @@ -75,14 +78,18 @@ KLet(x1, K(a1), KLet(x2, K(a2), KAop(o, x1, x2))) } case Call(name: String, args: List[Exp]) => { - val args_new = args.map{a => (Fresh("x"), K(a))} + val args_new = args.map{a => (Fresh("tmp"), K(a))} def aux(as: List[(String, KExp)]) : KExp = as match { case Nil => KCall(name, args_new.map(_._1)) case (x, a)::rest => KLet(x, a, aux(rest)) } aux(args_new) } - + case If(Bop("==", b1, b2), e1, e2) => { + val x1 = Fresh("tmp") + val x2 = Fresh("tmp") + KLet(x1, K(b1), KLet(x2, K(b2), KIfeq(x1, x2, K(e1), K(e2)))) + } } def Denest(e: KExp) : KExp = e match { @@ -93,12 +100,16 @@ } insert(Denest(e1)) } + case KIfeq(x1, x2, e1, e2) => KIfeq(x1, x2, Denest(e1), Denest(e2)) case _ => e } -val e = Aop("*", Aop("+", Num(1), Call("foo", List(Num(2), Num(3)))), Num(4)) + +val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4)) println(K(e)) +println() println(Denest(K(e))) +println() @@ -118,36 +129,33 @@ -// compile expressions -def compile_exp(a: Exp, env : Env, k: Int) : (String, Int) = a match { - case Num(i) => (i"%$k = add i32 0, i32 $i", k) - case Var(s) => (i"%$k = add i32 0, i32 %${env(s)}", k) - case Aop("+", a1, a2) => { - val (cs1, k1) = compile_exp(a1, env, k) - val (cs2, k2) = compile_exp(a2, env, k1 + 1) - (cs1 ++ cs2 ++ i"%${k2+1} = add i32 %$k1, i32 %$k2", k2 + 1) - } - case Aop("-", a1, a2) => { - val (cs1, k1) = compile_exp(a1, env, k) - val (cs2, k2) = compile_exp(a2, env, k1 + 1) - (cs1 ++ cs2 ++ i"%${k2+1} = sub i32 %$k1, i32 %$k2", k2 + 1) +// compile K expressions +def compile_exp(a: KExp) : String = a match { + case KNum(i) => s"?$i?" + case KVar(s) => s"?$s?" + case KAop("+", x1, x2) => s"add i32 %$x1, i32 %$x2" + case KAop("-", x1, x2) => s"sub i32 %$x1, i32 %$x2" + case KAop("*", x1, x2) => s"mul i32 %$x1, i32 %$x2" + case KLet(x: String, e1: KExp, e2: KExp) => { + val is1 = compile_exp(e1) + val is2 = compile_exp(e2) + i"%$x = $is1" ++ is2 } - case Aop("*", a1, a2) => { - val (cs1, k1) = compile_exp(a1, env, k) - val (cs2, k2) = compile_exp(a2, env, k1 + 1) - (cs1 ++ cs2 ++ i"%${k2+1} = mul i32 %$k1, i32 %$k2", k2 + 1) + case KIfeq(x1, x2, a1, a2) => { + val if_br = Fresh("if_br") + val else_br = Fresh("else_br") + val x = Fresh("tmp") + i"%$x = icmp eq i32 %$x1, i32 %$x2" ++ + i"br i1 %$x, label %$if_br, label %$else_br" ++ + l"\n$if_br" ++ + compile_exp(a1) ++ + l"\n$else_br" ++ + compile_exp(a2) } - /* - case If(b, a1, a2) => { - val if_else = Fresh("If_else") - val if_end = Fresh("If_end") - compile_bexp(b, env, if_else) ++ - compile_exp(a1, env) ++ - i"goto $if_end" ++ - l"$if_else" ++ - compile_exp(a2, env) ++ - l"$if_end" + case KCall(x1, args) => { + s"Call $x1 ($args)" } +/* case Call(name, args) => { val is = "I" * args.length args.map(a => compile_exp(a, env)).mkString ++ @@ -164,10 +172,7 @@ */ } -val e = Aop("*", Aop("+", Num(2), Num(4)), Num(5)) -compile_exp(e, Map(), 1)._1.mkString - - +/* // compile boolean expressions def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { case Bop("==", a1, a2) => @@ -179,28 +184,24 @@ case Bop("<=", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpgt $jmp" } +*/ // compile function for declarations and main def compile_decl(d: Decl) : String = d match { - case Def(name, args, a) => { - val env = args.zipWithIndex.toMap - val is = "I" * args.length - m".method public static $name($is)I" ++ - m".limit locals ${args.length.toString}" ++ - m".limit stack ${1 + max_stack_exp(a)}" ++ - l"${name}_Start" ++ - compile_exp(a, env) ++ - i"ireturn" ++ - m".end method\n" + case Def(name, args, body) => { + println(s"DEF\n $name ($args) = \nBODY:") + println(Denest(K(body))) + println() + counter = -1 + m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++ + compile_exp(Denest(K(body))) ++ + m"}\n" } - case Main(a) => { - m".method public static main([Ljava/lang/String;)V" ++ - m".limit locals 200" ++ - m".limit stack 200" ++ - compile_exp(a, Map()) ++ - i"invokestatic XXX/XXX/write(I)V" ++ - i"return" ++ - m".end method\n" + case Main(body) => { + m"define i32 @main() {" ++ + compile_exp(Denest(K(body))) ++ + i"ret i32 0" ++ + m"}\n" } } @@ -222,10 +223,12 @@ def compile(class_name: String) : String = { val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) - val instructions = ast.map(compile_decl).mkString - (library + instructions).replaceAllLiterally("XXX", class_name) + println(ast(0).toString ++ "\n") + val instructions = List(ast(0), ast(2)).map(compile_decl).mkString + instructions } +/* def compile_to_file(class_name: String) = { val output = compile(class_name) scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) @@ -236,7 +239,7 @@ (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!)) } - +*/ // some examples of .fun files //compile_to_file("fact") @@ -244,8 +247,8 @@ //compile_and_run("defs") -def main(args: Array[String]) = - compile_and_run(args(0)) +def main(args: Array[String]) : Unit = + println(compile(args(0))) } \ No newline at end of file