generate LLVM bit code

 input = ARGV[0]
 if !input
   puts 'bf.rb <hoge.bf>'
   exit
 end
 
 code = File.read(input)
 
 File.open('out.ll', 'w') do |of|
   of.puts %Q(
 define i32 @main() {
   %retval = alloca i32
 
   %m = alloca[100000 x i8]
   %m3 = bitcast [100000 x i8]* %m to i8*
   call void @llvm.memset.i64( i8* %m3, i8 0, i64 100000, i32 1 )
 
   %p = alloca i8*
   %mp = bitcast[100000 x i8]* %m to i8*
   %mp2 = getelementptr i8* %mp, i64 50000
   store i8* %mp2, i8** %p, align 8
 )
 
   tmpnum = 0
   ntmp = proc{tmpnum+=1}
 
   branches = []
   loopnum = 0
 
   code.split('').each do |b|
     case b[0]
     when ?+
       of.puts %Q(
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = load i8* %tmp#{a}, align 4
   %tmp#{c=ntmp[]} = add i8 %tmp#{b}, 1
   store i8 %tmp#{c}, i8* %tmp#{a}, align 4
 )
     when ?-
       of.puts %Q(
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = load i8* %tmp#{a}, align 4
   %tmp#{c=ntmp[]} = sub i8 %tmp#{b}, 1
   store i8 %tmp#{c}, i8* %tmp#{a}, align 4
 )
     when ?>
       of.puts %Q(
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = getelementptr i8* %tmp#{a}, i64 1
   store i8* %tmp#{b}, i8** %p, align 8
 )
     when ?<
       of.puts %Q(
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = getelementptr i8* %tmp#{a}, i64 -1
   store i8* %tmp#{b}, i8** %p, align 8
 )
     when ?[
       l = loopnum += 1
       branches.push(loopnum)
 
       of.puts %Q(
   br label %ls#{l}
 ls#{l}:
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = load i8* %tmp#{a}, align 4
   %tmp#{c=ntmp[]} = icmp ne i8 %tmp#{b}, 0
   br i1 %tmp#{c}, label %ll#{l}, label %le#{l}
 ll#{l}:
 )
     when ?]
       l = branches.pop
 
       of.puts %Q(
   br label %ls#{l}
 le#{l}:
 )
     when ?.
       of.puts %Q(
   %tmp#{a=ntmp[]} = load i8** %p, align 8
   %tmp#{b=ntmp[]} = load i8* %tmp#{a}, align 4
   %tmp#{c=ntmp[]} = zext i8 %tmp#{b} to i32
   call i32 @putchar(i32 %tmp#{c}) nounwind
 )
     when ?,
       of.puts %Q(
   %tmp#{a=ntmp[]} = call i32 @getchar() nounwind
   %tmp#{b=ntmp[]} = load i8** %p, align 8
   %tmp#{c=ntmp[]} = trunc i32 %tmp#{a} to i8
   store i8 %tmp#{c}, i8* %tmp#{b}, align 4
 )
     else
     end
   end
 
   if !branches.empty?
     raise 'unmatched ['
   end
 
   of.puts %Q(
   store i32 0, i32* %retval, align 4
   %retval2 = load i32* %retval
   ret i32 %retval2
 }
 
 declare i32 @putchar(i32)
 declare i32 @getchar()
 declare void @llvm.memset.i64(i8*, i8, i64, i32) nounwind
 )
 end
 
 puts 'Compiling...'
 system("llvm-as -f out.ll")
 if $? != 0
   exit $?
 end
 system("wc out.bc")
 
 puts 'Assembling...'
 system("llc -f out.bc")
 if $? != 0
   exit $?
 end
 system("wc out.s")
 
 puts 'Running...'
 system("lli out.bc")
 if $? != 0
   exit $?
 end

<< 15/26 >>
First Last