Archive for September, 2008
compiling a standalone binary
I added support for function types with variable arguments thus allowing us to call printf as an external function. This is very important as it allows us to tell the world how much we like grapes. Here is how you would compile a standalone executable that states your feelings about grapes:
require 'llvm' include LLVM m = LLVM::Module.new('grapes') ExecutionEngine.get(m) char_star = Type.pointer(Type::Int8Ty) main_type = Type.function(Type::Int32Ty, [ Type::Int32Ty, Type.pointer(char_star) ]) ftype = Type.function(Type::Int32Ty, [char_star], true) printf = m.external_function('printf', ftype) main = m.get_or_insert_function('main', main_type) b = main.create_block.builder grapes_str = b.create_global_string_ptr("I LIKE GRAPES!\n") b.call(printf, grapes_str) b.return(0.llvm(Type::Int32Ty)) puts m.inspect m.write_bitcode("main.o")
What happens when you run this program? First, you will see the resulting llvm code on the console:
; ModuleID = 'grapes' internal constant [16 x i8] c"I LIKE GRAPES!\0A\00" ; <[16 x i8]*>:0 [#uses=1] declare void @abort() declare i32 @printf(i8*, ...) define i32 @main(i32, i8**) { bb: call i32 (i8*, ...)* @printf( i8* getelementptr ([16 x i8]* @0, i32 0, i32 0) ) ; <i32>:2 [#uses=0] ret i32 0 }
This all got turned into bitcode and saved in the file “main.o”. Now all you have to do is link it with the command:
llvm-ld --native main.o
Now you have a lovely a.out file which is a little native binary bursting with grape love:
$ ./a.out I LIKE GRAPES!