VSL - The compiler.llvm.execution Structure
# Copyright 2011 Petter Urkedal
#
# This file is part of the Viz Standard Library <http://www.vizlang.org/>.
#
# The Viz Standard Library (VSL) is free software: you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The VSL is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
# more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the VSL. If not, see <http://www.gnu.org/licenses/>.
open pervasive
open effect
open core
open target
open foreign.cabi.memory
open foreign.cabi.utils
open:c "llvm-c/ExecutionEngine.h"
open:c "compiler/llvm_suppl.h"
# Camlviz work-around.
use cabi.type_c ltype "LLVMTypeRef"
use cabi.type_c value "LLVMValueRef"
use cabi.type_c module "LLVMModuleRef"
use cabi.type_c target_data "LLVMTargetDataRef"
type:c generic_value := "LLVMGenericValueRef"
val:c link_in_jit : ψ /~ unit := "LLVMLinkInJIT"
val:c link_in_interpreter : ψ /~ unit := "LLVMLinkInInterpreter"
in generic_value
type t := generic_value
val of_int : ltype ψ → int → t
val of_nativeint : ltype ψ → nativeint → t
val of_int32 : ltype ψ → int32 → t
val of_int64 : ltype ψ → int64 → t
val:c of_ptr : ptr ψ → t := "LLVMCreateGenericValueOfPointer"
val:c of_float : ltype ψ → float → t := "LLVMCreateGenericValueOfFloat"
val to_int : t → int
val to_nativeint : t → nativeint
val to_int32 : t → int32
val to_int64 : t → int64
val:c to_float : ltype ψ → t → float := "LLVMGenericValueToFloat"
val:c to_ptr : t → ptr ψ := "LLVMGenericValueToPointer"
val:c _of_int : ltype ψ → int → bool → t := "LLVMCreateGenericValueOfInt"
val:c _of_nativeint : ltype ψ → nativeint → bool → t
:= "LLVMCreateGenericValueOfInt"
val:c _of_int32 : ltype ψ → int32 → bool → t
:= "LLVMCreateGenericValueOfInt"
val:c _of_int64 : ltype ψ → int64 → bool → t
:= "LLVMCreateGenericValueOfInt"
let of_int t i be _of_int t i true
let of_nativeint t i be _of_nativeint t i true
let of_int32 t i be _of_int32 t i true
let of_int64 t i be _of_int64 t i true
val:c _to_int : t → bool → int := "LLVMGenericValueToInt"
val:c _to_int32 : t → bool → int32 := "LLVMGenericValueToInt"
val:c _to_int64 : t → bool → int64 := "LLVMGenericValueToInt"
val:c _to_nativeint : t → bool → nativeint := "LLVMGenericValueToInt"
let to_int gv be _to_int gv true
let to_int32 gv be _to_int32 gv true
let to_int64 gv be _to_int64 gv true
let to_nativeint gv be _to_nativeint gv true
in engine
type:c r ψ := "LLVMExecutionEngineRef"
val create : bool → module ψ → ψ /~ r ψ
val create_jit : int → module ψ → ψ /~ r ψ
val:c dispose : r ψ → ψ /~ unit := "LLVMDisposeExecutionEngine"
val:c run_static_constructors : r ψ → ψ /~ unit
:= "LLVMRunStaticConstructors"
val:c run_static_destructors : r ψ → ψ /~ unit
:= "LLVMRunStaticDestructors"
val run_function :
r ψ → value ψ → array generic_value.t → ψ /~ generic_value.t
val run_function_as_main :
r world → value world → array string → array (string × string) → io int
val:c free_machine_code_for_function : r ψ → value ψ → ψ /~ unit
:= "LLVMFreeMachineCodeForFunction"
val:c add_module : r ψ → module ψ → ψ /~ unit := "LLVMAddModule"
##val remove_module : r ψ → module ψ → ψ /~ option (module ψ)
val find_function : r ψ → string → ψ /~ option (value ψ)
val:c recompile_and_relink_function : r ψ → value ψ → ψ /~ ptr ψ
:= "LLVMRecompileAndRelinkFunction"
val:c get_target_data : r ψ → ψ /~ target_data ψ
:= "LLVMGetExecutionEngineTargetData"
val:c add_global_mapping : r ψ → value ψ → ptr ψ → ψ /~ unit
:= "LLVMAddGlobalMapping"
val:c get_pointer_to_global : r ψ → value ψ → ψ /~ ptr ψ
:= "LLVMGetPointerToGlobal"
### Implementation Details
val:c _of_ptr : ptr ψ → r ψ := ""
val:c _create : ptr ψ → module ψ → ptr ψ → ψ /~ bool
:= "LLVMCreateExecutionEngineForModule"
val:c _create_interpreter : ptr ψ → module ψ → ptr ψ → ψ /~ bool
:= "LLVMCreateInterpreterForModule"
let! create use_interp m
do unsafe_lalloc sizeof_ptr what! at slot
let ok do (use_interp ⇒ _create_interpreter; _create) slot m slot
let ee_or_err do unsafe_load_ptr offset.zero slot
if ok be _of_ptr ee_or_err
else let err do unsafe_copy_cstring ee_or_err
fail err
val:c _create_jit : ptr ψ → module ψ → int → ptr ψ → ψ /~ bool
:= "LLVMCreateJITCompilerForModule"
let! create_jit optlev m
do unsafe_lalloc (offset.scale 2 sizeof_ptr) what! at ee_slot
let err_slot be ptr.add sizeof_ptr ee_slot
let not_ok do _create_jit ee_slot m optlev err_slot
if not_ok
let err_ptr do unsafe_load_ptr offset.zero err_slot
let err do unsafe_copy_cstring err_ptr
fail err
let ee_ptr do unsafe_load_ptr offset.zero ee_slot
be _of_ptr ee_ptr
{#
val:c _create_jit : module ψ → int → ψ /~ option (r ψ) := "LLVMCreateJIT"
let! create_jit optlev m
do _create_jit m optlev >>= what!
at none% fail
at some% ee be ee
#}
val:c _run_function_as_main :
r world → value world → int → ptr world → ptr world → io int
:= "LLVMRunFunctionAsMain"
let! run_function_as_main ee f argv env
let n_argv be array.length argv
let n_env be array.length env
let p_argv do malloc_ptrarray_init n_argv
(i ↦ malloc_strcpy_string (array.get i argv))
let p_env do malloc_ptrarray_init (n_env + 1) what!
at i if i = n_env be ptr.get_zero pocket_tag
let (k, v) be array.get i env
do malloc_strcpy_string (string.cat_list [k; "="; v;])
let r do _run_function_as_main ee f n_argv p_argv p_env
do unsafe_ptrarray_free_elements p_argv n_argv
do unsafe_ptrarray_free_elements p_env n_env
do unsafe_free p_argv
do unsafe_free p_env
be r
val:c _run_function : r ψ → value ψ → int → ptr ψ → ψ /~ generic_value
:= "LLVMRunFunction"
let! run_function ee f args
let n_args be array.length args
let p_args do malloc_ptrarray_init n_args
(i ↦ unsafe_custom_load_ptr (array.get i args))
let r do _run_function ee f n_args p_args
do unsafe_free p_args
be r
val:c _value_of_ptr : ptr ψ → value ψ := ""
val:c _find_function : r ψ → string → ptr ψ → ψ /~ bool
:= "LLVMFindFunction"
let! find_function ee name
do unsafe_lalloc sizeof_ptr what! at p
let not_ok do _find_function ee name p
if not_ok be none
be some (_value_of_ptr p)