1 /*===-- executionengine_ocaml.c - LLVM OCaml Glue ---------------*- C++ -*-===*\ 2 |* *| 3 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 |* Exceptions. *| 5 |* See https://llvm.org/LICENSE.txt for license information. *| 6 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 |* *| 8 |*===----------------------------------------------------------------------===*| 9 |* *| 10 |* This file glues LLVM's OCaml interface to its C interface. These functions *| 11 |* are by and large transparent wrappers to the corresponding C functions. *| 12 |* *| 13 |* Note that these functions intentionally take liberties with the CAMLparamX *| 14 |* macros, since most of the parameters are not GC heap objects. *| 15 |* *| 16 \*===----------------------------------------------------------------------===*/ 17 18 #include <string.h> 19 #include <assert.h> 20 #include "llvm-c/Core.h" 21 #include "llvm-c/ExecutionEngine.h" 22 #include "llvm-c/Target.h" 23 #include "caml/alloc.h" 24 #include "caml/custom.h" 25 #include "caml/fail.h" 26 #include "caml/memory.h" 27 #include "caml/callback.h" 28 29 void llvm_raise(value Prototype, char *Message); 30 31 /* unit -> bool */ 32 value llvm_ee_initialize(value Unit) { 33 LLVMLinkInMCJIT(); 34 35 return Val_bool(!LLVMInitializeNativeTarget() && 36 !LLVMInitializeNativeAsmParser() && 37 !LLVMInitializeNativeAsmPrinter()); 38 } 39 40 /* llmodule -> llcompileroption -> ExecutionEngine.t */ 41 LLVMExecutionEngineRef llvm_ee_create(value OptRecordOpt, LLVMModuleRef M) { 42 value OptRecord; 43 LLVMExecutionEngineRef MCJIT; 44 char *Error; 45 struct LLVMMCJITCompilerOptions Options; 46 47 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); 48 if (OptRecordOpt != Val_int(0)) { 49 OptRecord = Field(OptRecordOpt, 0); 50 Options.OptLevel = Int_val(Field(OptRecord, 0)); 51 Options.CodeModel = Int_val(Field(OptRecord, 1)); 52 Options.NoFramePointerElim = Int_val(Field(OptRecord, 2)); 53 Options.EnableFastISel = Int_val(Field(OptRecord, 3)); 54 Options.MCJMM = NULL; 55 } 56 57 if (LLVMCreateMCJITCompilerForModule(&MCJIT, M, &Options, sizeof(Options), 58 &Error)) 59 llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); 60 return MCJIT; 61 } 62 63 /* ExecutionEngine.t -> unit */ 64 value llvm_ee_dispose(LLVMExecutionEngineRef EE) { 65 LLVMDisposeExecutionEngine(EE); 66 return Val_unit; 67 } 68 69 /* llmodule -> ExecutionEngine.t -> unit */ 70 value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { 71 LLVMAddModule(EE, M); 72 return Val_unit; 73 } 74 75 /* llmodule -> ExecutionEngine.t -> llmodule */ 76 value llvm_ee_remove_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { 77 LLVMModuleRef RemovedModule; 78 char *Error; 79 if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) 80 llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); 81 return Val_unit; 82 } 83 84 /* ExecutionEngine.t -> unit */ 85 value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) { 86 LLVMRunStaticConstructors(EE); 87 return Val_unit; 88 } 89 90 /* ExecutionEngine.t -> unit */ 91 value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) { 92 LLVMRunStaticDestructors(EE); 93 return Val_unit; 94 } 95 96 extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData); 97 98 /* ExecutionEngine.t -> Llvm_target.DataLayout.t */ 99 value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { 100 value DataLayout; 101 LLVMTargetDataRef OrigDataLayout; 102 char *TargetDataCStr; 103 104 OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); 105 TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); 106 DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); 107 LLVMDisposeMessage(TargetDataCStr); 108 109 return DataLayout; 110 } 111 112 /* Llvm.llvalue -> int64 -> llexecutionengine -> unit */ 113 value llvm_ee_add_global_mapping(LLVMValueRef Global, value Ptr, 114 LLVMExecutionEngineRef EE) { 115 LLVMAddGlobalMapping(EE, Global, (void *)(Int64_val(Ptr))); 116 return Val_unit; 117 } 118 119 value llvm_ee_get_global_value_address(value Name, LLVMExecutionEngineRef EE) { 120 return caml_copy_int64( 121 (int64_t)LLVMGetGlobalValueAddress(EE, String_val(Name))); 122 } 123 124 value llvm_ee_get_function_address(value Name, LLVMExecutionEngineRef EE) { 125 return caml_copy_int64((int64_t)LLVMGetFunctionAddress(EE, String_val(Name))); 126 } 127