progs/fun/fun_llvm.sc
changeset 813 059f970287d1
parent 789 f0696713177b
child 819 fd88a0656164
equal deleted inserted replaced
812:2f9a0dcf61ae 813:059f970287d1
     1 // A Small LLVM Compiler for a Simple Functional Language
     1 // A Small LLVM Compiler for a Simple Functional Language
     2 // (includes an external lexer and parser)
     2 // (includes an external lexer and parser)
     3 //
     3 //
       
     4 //
     4 // call with 
     5 // call with 
     5 //
     6 //
       
     7 //     amm fun_llvm.sc main fact.fun
       
     8 //     amm fun_llvm.sc main defs.fun
       
     9 //
       
    10 // or
       
    11 //
     6 //     amm fun_llvm.sc write fact.fun
    12 //     amm fun_llvm.sc write fact.fun
     7 //
       
     8 //     amm fun_llvm.sc write defs.fun
    13 //     amm fun_llvm.sc write defs.fun
     9 //
    14 //
    10 // this will generate a .ll file. Other options are compile and run.
    15 //       this will generate an .ll file. 
    11 //
    16 //
    12 // You can interpret an .ll file using lli.
    17 // or 
       
    18 //
       
    19 //     amm fun_llvm.sc run fact.fun
       
    20 //     amm fun_llvm.sc run defs.fun
       
    21 //
       
    22 //
       
    23 // You can interpret an .ll file using lli, for example
       
    24 //
       
    25 //      lli fact.ll
    13 //
    26 //
    14 // The optimiser can be invoked as
    27 // The optimiser can be invoked as
    15 //
    28 //
    16 //      opt -O1 -S in_file.ll > out_file.ll
    29 //      opt -O1 -S in_file.ll > out_file.ll
    17 //      opt -O3 -S in_file.ll > out_file.ll
    30 //      opt -O3 -S in_file.ll > out_file.ll
    18 //
    31 //
    19 // The code produced for the various architectures can be obtains with
    32 // The code produced for the various architectures can be obtain with
    20 //   
    33 //   
    21 //   llc -march=x86 -filetype=asm in_file.ll -o -
    34 //   llc -march=x86 -filetype=asm in_file.ll -o -
    22 //   llc -march=arm -filetype=asm in_file.ll -o -  
    35 //   llc -march=arm -filetype=asm in_file.ll -o -  
    23 //
    36 //
    24 // Producing an executable can be achieved by
    37 // Producing an executable can be achieved by
    28 //    ./a.out
    41 //    ./a.out
    29 
    42 
    30 
    43 
    31 import $file.fun_tokens, fun_tokens._
    44 import $file.fun_tokens, fun_tokens._
    32 import $file.fun_parser, fun_parser._ 
    45 import $file.fun_parser, fun_parser._ 
    33 import scala.util._
       
    34 
    46 
    35 
    47 
    36 // for generating new labels
    48 // for generating new labels
    37 var counter = -1
    49 var counter = -1
    38 
    50 
   148   case "*" => "mul i32 "
   160   case "*" => "mul i32 "
   149   case "-" => "sub i32 "
   161   case "-" => "sub i32 "
   150   case "/" => "sdiv i32 "
   162   case "/" => "sdiv i32 "
   151   case "%" => "srem i32 "
   163   case "%" => "srem i32 "
   152   case "==" => "icmp eq i32 "
   164   case "==" => "icmp eq i32 "
   153   case "<=" => "icmp sle i32 "    // signed less or equal
   165   case "<=" => "icmp sle i32 "     // signed less or equal
   154   case "<" => "icmp slt i32 "     // signed less than
   166   case "<"  => "icmp slt i32 "     // signed less than
   155 }
   167 }
   156 
   168 
       
   169 // compile K values
   157 def compile_val(v: KVal) : String = v match {
   170 def compile_val(v: KVal) : String = v match {
   158   case KNum(i) => s"$i"
   171   case KNum(i) => s"$i"
   159   case KVar(s) => s"%$s"
   172   case KVar(s) => s"%$s"
   160   case Kop(op, x1, x2) => 
   173   case Kop(op, x1, x2) => 
   161     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
   174     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
   209     compile_exp(CPS(body)(_ => KReturn(KNum(0)))) ++
   222     compile_exp(CPS(body)(_ => KReturn(KNum(0)))) ++
   210     m"}\n"
   223     m"}\n"
   211   }
   224   }
   212 }
   225 }
   213 
   226 
       
   227 
   214 // main compiler functions
   228 // main compiler functions
   215 
   229 def compile(prog: List[Decl]) : String = 
   216 def compile_prog(prog: List[Decl]) : String = 
       
   217   prelude ++ (prog.map(compile_decl).mkString)
   230   prelude ++ (prog.map(compile_decl).mkString)
   218 
   231 
   219 
   232 
       
   233 import ammonite.ops._
       
   234 
       
   235 
   220 @main
   236 @main
   221 def compile(fname: String) = {
   237 def main(fname: String) = {
   222     val path = os.pwd / fname
   238     val path = os.pwd / fname
   223     val file = fname.stripSuffix("." ++ path.ext)
   239     val file = fname.stripSuffix("." ++ path.ext)
   224     val tks = tokenise(os.read(path))
   240     val tks = tokenise(os.read(path))
   225     val ast = parse_tks(tks)
   241     val ast = parse_tks(tks)
   226     println(compile_prog(ast))
   242     println(compile(ast))
   227 }
   243 }
   228 
   244 
   229 @main
   245 @main
   230 def write(fname: String) = {
   246 def write(fname: String) = {
   231     val path = os.pwd / fname
   247     val path = os.pwd / fname
   232     val file = fname.stripSuffix("." ++ path.ext)
   248     val file = fname.stripSuffix("." ++ path.ext)
   233     val tks = tokenise(os.read(path))
   249     val tks = tokenise(os.read(path))
   234     val ast = parse_tks(tks)
   250     val ast = parse_tks(tks)
   235     val code = compile_prog(ast)
   251     val code = compile(ast)
   236     os.write.over(os.pwd / (file ++ ".ll"), code)
   252     os.write.over(os.pwd / (file ++ ".ll"), code)
   237 }
   253 }
   238 
   254 
   239 @main
   255 @main
   240 def run(fname: String) = {
   256 def run(fname: String) = {
   241     val path = os.pwd / fname
   257     val path = os.pwd / fname
   242     val file = fname.stripSuffix("." ++ path.ext)
   258     val file = fname.stripSuffix("." ++ path.ext)
   243     val tks = tokenise(os.read(path))
   259     write(fname)  
   244     val ast = parse_tks(tks)
       
   245     val code = compile_prog(ast)
       
   246     os.write.over(os.pwd / (file ++ ".ll"), code)
       
   247     os.proc("llc", "-filetype=obj", file ++ ".ll").call()
   260     os.proc("llc", "-filetype=obj", file ++ ".ll").call()
   248     os.proc("gcc", file ++ ".o", "-o", file).call()
   261     os.proc("gcc", file ++ ".o", "-o", file ++ ".bin").call()
   249     print(os.proc(os.pwd / file).call().out.string)
   262     os.proc(os.pwd / (file ++ ".bin")).call(stdout = os.Inherit)
   250 }
   263     println(s"done.")
   251 
   264 }
   252 
   265 
   253 
   266 
   254 
   267 
   255 
   268 
       
   269