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