Tuesday, 15 March 2011

Ho-ho-ho. LLVM in Parrot is getting closer :)

Current results of few days of reading LLVM docs/tutorials and one day of hacking.

Basically we can create something like:
int foo() {
     printf("Hello World\n");
     return 42;
} 


In run-time. With LLVM. JIT in parrot is getting closer :)



There is full code:

~/src/parrot (opsc_llvm)$ cat llvm.nqp 
#! parrot-nqp

pir::load_bytecode("LLVM.pbc");

pir::loadlib("llvm_engine");

# Create new module.
my $module := LLVM::Module.new.BUILD("HELLO");

# Create forward declaration of "printf".
my $printf := $module.add_function(
    "printf",                                   # name
    LLVM::Type::int32(),                        # return type
    LLVM::Type::pointer(LLVM::Type::int8()),    # first arg - char*
    :va_args<1>                                 # varargs
);

# Add it to module
my $function := $module.add_function("hello", LLVM::Type::int32());

# Start building our function
my $bb := $function.append_basic_block("the_block");

# We'll use Builder. He've got some brains about how to deal with LLVM.
my $builder := LLVM::Builder.new.BUILD();

# Start within block.
$builder.set_position($bb);

# This will be our argument to "printf"
my $hello_str := $builder.global_string("****** Hello LLVM World ******\n", "");

# Call "printf"
$builder.call($printf, $hello_str);

# Return from function
my $answer := LLVM::Constant::integer(42);
$builder.ret($answer);

# Let's execute it
# We need some engine
my $engine := pir::new__psp("LLVM_Engine", $module.unwrap());

# .create return NCI PMC. 
my $call   := $engine.create(
    $function.unwrap(),     # Function to call
    "I"                     # Singnature. In this case - return int, no args
);

# Call it!
my $res := $call();

pir::say("Result of call: $res");

# vim: ft=perl6

~/src/parrot (opsc_llvm)$ ./parrot-nqp llvm.nqp 
****** Hello LLVM World ******
Result of call: 42