progs/fun_llvm.scala
changeset 655 3d04ee04966d
parent 654 fb6192488b91
child 656 cfc0e730bcda
equal deleted inserted replaced
654:fb6192488b91 655:3d04ee04966d
     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 }