|      5 // |      5 // | 
|      6 //     scala fun_llvm.scala fact |      6 //     scala fun_llvm.scala fact | 
|      7 // |      7 // | 
|      8 //     scala fun_llvm.scala defs |      8 //     scala fun_llvm.scala defs | 
|      9 // |      9 // | 
|     10 // this will generate a .ll file |     10 // this will generate a .ll file. You can interpret this file | 
|         |     11 // using lli. | 
|         |     12 // | 
|         |     13 // The optimiser can be invoked as | 
|         |     14 // | 
|         |     15 //      opt -O1 -S in_file.ll > out_file.ll | 
|         |     16 //      opt -O3 -S in_file.ll > out_file.ll | 
|         |     17 // | 
|         |     18 // The code produced for the various architectures can be obtains with | 
|         |     19 //    | 
|         |     20 //   llc -march=x86 -filetype=asm in_file.ll -o - | 
|         |     21 //   llc -march=arm -filetype=asm in_file.ll -o -   | 
|         |     22 // | 
|         |     23 // Producing an executable can be achieved by | 
|         |     24 // | 
|         |     25 //    llc -filetype=obj in_file.ll | 
|         |     26 //    gcc in_file.o -o a.out | 
|         |     27 //    ./a.out | 
|         |     28  | 
|     11  |     29  | 
|     12  |     30  | 
|     13 object Compiler { |     31 object Compiler { | 
|     14  |     32  | 
|     15 import java.io._   |     33 import java.io._   | 
|     32 case class Aop(o: String, a1: Exp, a2: Exp) extends Exp |     50 case class Aop(o: String, a1: Exp, a2: Exp) extends Exp | 
|     33 case class Sequence(e1: Exp, e2: Exp) extends Exp |     51 case class Sequence(e1: Exp, e2: Exp) extends Exp | 
|     34 case class Bop(o: String, a1: Exp, a2: Exp) extends BExp |     52 case class Bop(o: String, a1: Exp, a2: Exp) extends BExp | 
|     35  |     53  | 
|     36  |     54  | 
|     37 // compiler - built-in functions  |         | 
|     38 // copied from http://www.ceng.metu.edu.tr/courses/ceng444/link/jvm-cpm.html |         | 
|     39 // |         | 
|     40  |         | 
|     41  |         | 
|     42 // for generating new labels |     55 // for generating new labels | 
|     43 var counter = -1 |     56 var counter = -1 | 
|     44  |     57  | 
|     45 def Fresh(x: String) = { |     58 def Fresh(x: String) = { | 
|     46   counter += 1 |     59   counter += 1 | 
|     54 case class KVar(s: String) extends KVal |     67 case class KVar(s: String) extends KVal | 
|     55 case class KNum(i: Int) extends KVal |     68 case class KNum(i: Int) extends KVal | 
|     56 case class KAop(o: String, v1: KVal, v2: KVal) extends KVal |     69 case class KAop(o: String, v1: KVal, v2: KVal) extends KVal | 
|     57 case class KBop(o: String, v1: KVal, v2: KVal) extends KVal |     70 case class KBop(o: String, v1: KVal, v2: KVal) extends KVal | 
|     58 case class KCall(o: String, vrs: List[KVal]) extends KVal |     71 case class KCall(o: String, vrs: List[KVal]) extends KVal | 
|         |     72 case class KWrite(v: KVal) extends KVal | 
|     59  |     73  | 
|     60 case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp { |     74 case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp { | 
|     61   override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2" |     75   override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2" | 
|     62 } |     76 } | 
|     63 case class KLet(x: String, e1: KVal, e2: KExp) extends KExp { |     77 case class KLet(x: String, e1: KVal, e2: KExp) extends KExp { | 
|     64   override def toString = s"let $x = $e1 in \n$e2"  |     78   override def toString = s"let $x = $e1 in \n$e2"  | 
|     65 } |     79 } | 
|     66 case class KReturn(v: KVal) extends KExp |     80 case class KReturn(v: KVal) extends KExp | 
|     67  |     81  | 
|     68  |     82  | 
|     69 // CPS translation from Exp's to KExp's using a |     83 // CPS translation from Exps to KExps using a | 
|     70 // continuation k. |     84 // continuation k. | 
|     71 def CPS(e: Exp)(k: KVal => KExp) : KExp = e match { |     85 def CPS(e: Exp)(k: KVal => KExp) : KExp = e match { | 
|     72   case Var(s) => k(KVar(s))  |     86   case Var(s) => k(KVar(s))  | 
|     73   case Num(i) => k(KNum(i)) |     87   case Num(i) => k(KNum(i)) | 
|     74   case Aop(o, e1, e2) => { |     88   case Aop(o, e1, e2) => { | 
|     77       CPS(e2)(y2 => KLet(z, KAop(o, y1, y2), k(KVar(z))))) |     91       CPS(e2)(y2 => KLet(z, KAop(o, y1, y2), k(KVar(z))))) | 
|     78   } |     92   } | 
|     79   case If(Bop(o, b1, b2), e1, e2) => { |     93   case If(Bop(o, b1, b2), e1, e2) => { | 
|     80     val z = Fresh("tmp") |     94     val z = Fresh("tmp") | 
|     81     CPS(b1)(y1 =>  |     95     CPS(b1)(y1 =>  | 
|     82       CPS(b2)(y2 => KLet(z, KBop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k))))) |     96       CPS(b2)(y2 =>  | 
|         |     97         KLet(z, KBop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k))))) | 
|     83   } |     98   } | 
|     84   case Call(name, args) => { |     99   case Call(name, args) => { | 
|     85     def aux(args: List[Exp], vs: List[KVal]) : KExp = args match { |    100     def aux(args: List[Exp], vs: List[KVal]) : KExp = args match { | 
|     86       case Nil => { |    101       case Nil => { | 
|     87           val z = Fresh("tmp") |    102           val z = Fresh("tmp") | 
|     94   case Sequence(e1, e2) => { |    109   case Sequence(e1, e2) => { | 
|     95     val z = Fresh("tmp") |    110     val z = Fresh("tmp") | 
|     96     CPS(e1)(y1 =>  |    111     CPS(e1)(y1 =>  | 
|     97       CPS(e2)(y2 => KLet("_", y1, KLet(z, y2, k(KVar(z)))))) |    112       CPS(e2)(y2 => KLet("_", y1, KLet(z, y2, k(KVar(z)))))) | 
|     98   } |    113   } | 
|         |    114   case Write(e) => { | 
|         |    115     val z = Fresh("tmp") | 
|         |    116     CPS(e)(y => KLet(z, KWrite(y), k(KVar(z)))) | 
|         |    117   } | 
|     99 }    |    118 }    | 
|    100  |    119  | 
|    101 def CPSi(e: Exp) = CPS(e)(KReturn) |    120 def CPSi(e: Exp) = CPS(e)(KReturn) | 
|    102  |    121  | 
|    103 // some testcases |    122 // some testcases | 
|    159     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" |    178     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" | 
|    160   case KBop(op, x1, x2) =>  |    179   case KBop(op, x1, x2) =>  | 
|    161     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" |    180     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" | 
|    162   case KCall(x1, args) =>  |    181   case KCall(x1, args) =>  | 
|    163     s"call i32 @$x1 (${args.map(compile_val).mkString("i32 ", ", i32 ", "")})" |    182     s"call i32 @$x1 (${args.map(compile_val).mkString("i32 ", ", i32 ", "")})" | 
|         |    183   case KWrite(x1) => | 
|         |    184     s"call i32 @printInt (i32 ${compile_val(x1)})" | 
|    164 } |    185 } | 
|    165  |    186  | 
|    166 // compile K expressions |    187 // compile K expressions | 
|    167 def compile_exp(a: KExp) : String = a match { |    188 def compile_exp(a: KExp) : String = a match { | 
|    168   case KReturn(v) => |    189   case KReturn(v) => | 
|    178     l"\n$else_br" ++  |    199     l"\n$else_br" ++  | 
|    179     compile_exp(e2) |    200     compile_exp(e2) | 
|    180   } |    201   } | 
|    181 } |    202 } | 
|    182  |    203  | 
|    183 /*  case Write(a1) => { |    204  | 
|    184     compile_exp(a1, env) ++ |    205 val prelude = """ | 
|    185     i"dup" ++ |    206 @.str = private constant [4 x i8] c"%d\0A\00" | 
|    186     i"invokestatic XXX/XXX/write(I)V" |    207  | 
|    187   } |    208 declare i32 @printf(i8*, ...) | 
|    188 */ |    209  | 
|    189  |    210 define i32 @printInt(i32 %x) { | 
|         |    211    %t0 = getelementptr [4 x i8], [4 x i8]* @.str, i32 0, i32 0 | 
|         |    212    call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %x)  | 
|         |    213    ret i32 %x | 
|         |    214 } | 
|         |    215  | 
|         |    216 """ | 
|    190  |    217  | 
|    191  |    218  | 
|    192 // compile function for declarations and main |    219 // compile function for declarations and main | 
|    193 def compile_decl(d: Decl) : String = d match { |    220 def compile_decl(d: Decl) : String = d match { | 
|    194   case Def(name, args, body) => {  |    221   case Def(name, args, body) => {  | 
|    217   Using(new ObjectInputStream(new FileInputStream(fname))) { |    244   Using(new ObjectInputStream(new FileInputStream(fname))) { | 
|    218     in => in.readObject.asInstanceOf[T] |    245     in => in.readObject.asInstanceOf[T] | 
|    219   } |    246   } | 
|    220 } |    247 } | 
|    221  |    248  | 
|    222 def compile(class_name: String) : String = { |    249 def compile(fname: String) : String = { | 
|    223   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil)  |    250   val ast = deserialise[List[Decl]](fname ++ ".prs").getOrElse(Nil)  | 
|    224   ast.map(compile_decl).mkString |    251   prelude ++ (ast.map(compile_decl).mkString) | 
|    225 } |    252 } | 
|    226  |    253  | 
|    227 /* |    254 def compile_to_file(fname: String) = { | 
|    228 def compile_to_file(class_name: String) = { |    255   val output = compile(fname) | 
|    229   val output = compile(class_name) |    256   scala.tools.nsc.io.File(s"${fname}.ll").writeAll(output) | 
|    230   scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) |    257 } | 
|    231 } |    258  | 
|    232  |    259 def compile_and_run(fname: String) : Unit = { | 
|    233 def compile_and_run(class_name: String) : Unit = { |    260   compile_to_file(fname) | 
|    234   compile_to_file(class_name) |    261   (s"llc -filetype=obj ${fname}.ll").!! | 
|    235   (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |    262   (s"gcc ${fname}.o -o a.out").!! | 
|    236   println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!)) |    263   println("Time: " + time_needed(2, (s"./a.out").!)) | 
|    237 } |    264 } | 
|    238 */ |         | 
|    239  |    265  | 
|    240 // some examples of .fun files |    266 // some examples of .fun files | 
|    241 //compile_to_file("fact") |    267 //compile_to_file("fact") | 
|    242 //compile_and_run("fact") |    268 //compile_and_run("fact") | 
|    243 //compile_and_run("defs") |    269 //compile_and_run("defs") | 
|    244  |    270  | 
|    245  |    271  | 
|    246 def main(args: Array[String]) : Unit =  |    272 def main(args: Array[String]) : Unit =  | 
|    247    println(compile(args(0))) |    273    //println(compile(args(0))) | 
|    248  |    274    compile_and_run(args(0)) | 
|    249  |    275  | 
|    250 } |    276 } |