[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. 1. Run `make` to build the extension. 1. You'll also have to add LLVM's lib path to `LD_LIBRARY_PATH`. 1. 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 ; [#uses=2] store i32 %0, i32* %arg0 %arg01 = load i32* %arg0 ; [#uses=1] %add6 = add i32 %arg01, 6 ; [#uses=1] %add4 = add i32 %add6, 4 ; [#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 ; [#uses=1] ret i32 %add4 } ====== **Transforming Tcl into LLVM bit code** The LLVM wrapper has limited support for converting Tcl into LLVM bit code and is based on the output of [tcl::unsupported::disassemble]. Current (stringent) limitation are: * all variables are 32 bit integers (no strings, floats, lists, arrays, dicts, ...) * all proc's return a single 32 bit integer * all proc's must be know at convert time (example still to be added) <>Enter Category Here