Version 6 of llvmtcl

Updated 2010-05-21 16:06:19 by jos

jdc 21-may-2010 To learn LLVM I made a wrapper got LLVM's C API. This wrapper is available at: http://github.com/jdc8/llvmtcl

Building the wrapper

The wrapper uses LLVM's C API as found in LLVM's header file Core.h in include\llvm-c.

Requirements:

  • LLVM 2.7
  • Tcl 8.5 (most test have been done with Tcl HEAD)

There is a Makefile to build the extension;

  1. Edit the Makefile to specify the paths to your Tcl and LLVM.
  2. Run make to build the extension.
  3. You'll also have to add LLVM's lib path to LD_LIBRARY_PATH.
  4. Run make test to check it the extension is working

Using the LLVM API

Building a LLVM module and function:

lappend auto_path .
package require llvmtcl

namespace import llvmtcl::*

# Initialize the JIT
LLVMLinkInJIT
LLVMInitializeNativeTarget

# Create a module and builder
set m [LLVMModuleCreateWithName "testmodule"]
set bld [LLVMCreateBuilder]

# Create a plus10 function, taking one argument and adding 6 and 4 to it
set ft [LLVMFunctionType [LLVMInt32Type] [list [LLVMInt32Type]] 0]
set plus10 [LLVMAddFunction $m "plus10" $ft]

# Create constants
set c6 [LLVMConstInt [LLVMInt32Type] 6 0]
set c4 [LLVMConstInt [LLVMInt32Type] 4 0]

# Create the basic blocks
set entry [LLVMAppendBasicBlock $plus10 entry]

# Put arguments on the stack to avoid having to write select and/or phi nodes
LLVMPositionBuilderAtEnd $bld $entry
set arg0_1 [LLVMGetParam $plus10 0]
set arg0_2 [LLVMBuildAlloca $bld [LLVMInt32Type] arg0]
set arg0_3 [LLVMBuildStore $bld $arg0_1 $arg0_2]

# Do add 10 in two steps to see the optimizer @ work

# Add 6
set arg0_4 [LLVMBuildLoad $bld $arg0_2 "arg0"]
set add6 [LLVMBuildAdd $bld $arg0_4 $c6 "add6"]

# Add 4
set add4 [LLVMBuildAdd $bld $add6 $c4 "add4"]

# Set return
LLVMBuildRet $bld $add4

# Show input
puts "----- Input --------------------------------------------------"
puts [LLVMDumpModule $m]

# Verify the module
lassign [LLVMVerifyModule $m LLVMReturnStatusAction] rt msg
if {$rt} {
    error $msg
}

This results in the following LLVM bit code:

; ModuleID = 'testmodule'

define i32 @plus10(i32) {
entry:
  %arg0 = alloca i32                              ; <i32*> [#uses=2]
  store i32 %0, i32* %arg0
  %arg01 = load i32* %arg0                        ; <i32> [#uses=1]
  %add6 = add i32 %arg01, 6                       ; <i32> [#uses=1]
  %add4 = add i32 %add6, 4                        ; <i32> [#uses=1]
  ret i32 %add4
}

Now execute it:

# Execute
lassign [LLVMCreateJITCompilerForModule $m 0] rt EE msg
set i [LLVMCreateGenericValueOfInt [LLVMInt32Type] 4 0]
set res [LLVMRunFunction $EE $plus10 $i]
puts "plus10(4) = [LLVMGenericValueToInt $res 0]\n"

Now optimize the LLVM module:

# Optimize
set td [LLVMCreateTargetData ""]
LLVMSetDataLayout $m [LLVMCopyStringRepOfTargetData $td]
LLVMOptimizeFunction $m $plus10 3 $td
LLVMOptimizeModule $m 3 0 1 1 1 0 $td

Result of optimization:

; ModuleID = 'testmodule'
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"

define i32 @plus10(i32) readnone {
entry:
  %add4 = add i32 %0, 10                          ; <i32> [#uses=1]
  ret i32 %add4
}

Transforming Tcl into LLVM bit code