blob: 816c966104a0b5b3e808f5370735f2b244b8037e [file] [log] [blame]
Gordon Henriksen8db172d2007-12-23 16:59:28 +00001/*===-- analysis_ocaml.c - LLVM Ocaml Glue ----------------------*- C++ -*-===*\
2|* *|
3|* The LLVM Compiler Infrastructure *|
4|* *|
5|* This file was developed by Gordon Henriksen and is distributed under the *|
6|* University of Illinois Open Source License. See LICENSE.TXT for details. *|
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 "llvm-c/ExecutionEngine.h"
19#include "caml/alloc.h"
20#include "caml/custom.h"
21#include "caml/fail.h"
22#include "caml/memory.h"
23#include <string.h>
24#include <assert.h>
25
26
27/* Can't use the recommended caml_named_value mechanism for backwards
28 compatibility reasons. This is largely equivalent. */
29static value llvm_ee_error_exn;
30
31CAMLprim value llvm_register_ee_exns(value Error) {
32 llvm_ee_error_exn = Field(Error, 0);
33 register_global_root(&llvm_ee_error_exn);
34 return Val_unit;
35}
36
37static void llvm_raise(value Prototype, char *Message) {
38 CAMLparam1(Prototype);
39 CAMLlocal1(CamlMessage);
40
41 CamlMessage = copy_string(Message);
42 LLVMDisposeMessage(Message);
43
44 raise_with_arg(Prototype, CamlMessage);
45 abort(); /* NOTREACHED */
46 CAMLnoreturn;
47}
48
49
50/*--... Operations on generic values .......................................--*/
51
52#define Genericvalue_val(v) (*(LLVMGenericValueRef *)(Data_custom_val(v)))
53
54static void llvm_finalize_generic_value(value GenVal) {
55 LLVMDisposeGenericValue(Genericvalue_val(GenVal));
56}
57
58static struct custom_operations generic_value_ops = {
59 (char *) "LLVMGenericValue",
60 llvm_finalize_generic_value,
61 custom_compare_default,
62 custom_hash_default,
63 custom_serialize_default,
64 custom_deserialize_default
65};
66
67static value alloc_generic_value(LLVMGenericValueRef Ref) {
68 value Val = alloc_custom(&generic_value_ops, sizeof(LLVMGenericValueRef), 0, 1);
69 Genericvalue_val(Val) = Ref;
70 return Val;
71}
72
73/* Llvm.lltype -> float -> t */
74CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) {
75 return alloc_generic_value(LLVMCreateGenericValueOfFloat(Ty, Double_val(N)));
76}
77
78/* 'a -> t */
79CAMLprim value llvm_genericvalue_of_value(value V) {
80 return alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)));
81}
82
83/* Llvm.lltype -> int -> t */
84CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) {
85 return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1));
86}
87
88/* Llvm.lltype -> int32 -> t */
89CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) {
90 return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32),
91 1));
92}
93
94/* Llvm.lltype -> nativeint -> t */
95CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) {
96 return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty,
97 Nativeint_val(NatInt),
98 1));
99}
100
101/* Llvm.lltype -> int64 -> t */
102CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) {
103 return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64),
104 1));
105}
106
107/* Llvm.lltype -> t -> float */
108CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) {
109 return copy_double(LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal)));
110}
111
112/* t -> 'a */
113CAMLprim value llvm_genericvalue_as_value(value GenVal) {
114 return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal)));
115}
116
117/* t -> int */
118CAMLprim value llvm_genericvalue_as_int(value GenVal) {
119 assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value)
120 && "Generic value too wide to treat as an int!");
121 return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1));
122}
123
124/* t -> int32 */
125CAMLprim value llvm_genericvalue_as_int32(value GenVal) {
126 assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32
127 && "Generic value too wide to treat as an int32!");
128 return copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1));
129}
130
131/* t -> int64 */
132CAMLprim value llvm_genericvalue_as_int64(value GenVal) {
133 assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64
134 && "Generic value too wide to treat as an int64!");
135 return copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1));
136}
137
138/* t -> nativeint */
139CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) {
140 assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value)
141 && "Generic value too wide to treat as a nativeint!");
142 return copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1));
143}
144
145
146/*--... Operations on execution engines ....................................--*/
147
148/* llmoduleprovider -> ExecutionEngine.t */
149CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleProviderRef MP) {
150 LLVMExecutionEngineRef Interp;
151 char *Error;
152 if (LLVMCreateExecutionEngine(&Interp, MP, &Error))
153 llvm_raise(llvm_ee_error_exn, Error);
154 return Interp;
155}
156
157/* llmoduleprovider -> ExecutionEngine.t */
158CAMLprim LLVMExecutionEngineRef
159llvm_ee_create_interpreter(LLVMModuleProviderRef MP) {
160 LLVMExecutionEngineRef Interp;
161 char *Error;
162 if (LLVMCreateInterpreter(&Interp, MP, &Error))
163 llvm_raise(llvm_ee_error_exn, Error);
164 return Interp;
165}
166
167/* llmoduleprovider -> ExecutionEngine.t */
168CAMLprim LLVMExecutionEngineRef
169llvm_ee_create_jit(LLVMModuleProviderRef MP) {
170 LLVMExecutionEngineRef JIT;
171 char *Error;
172 if (LLVMCreateJITCompiler(&JIT, MP, &Error))
173 llvm_raise(llvm_ee_error_exn, Error);
174 return JIT;
175}
176
177/* ExecutionEngine.t -> unit */
178CAMLprim value llvm_ee_dispose(LLVMExecutionEngineRef EE) {
179 LLVMDisposeExecutionEngine(EE);
180 return Val_unit;
181}
182
183/* llmoduleprovider -> ExecutionEngine.t -> unit */
184CAMLprim value llvm_ee_add_mp(LLVMModuleProviderRef MP,
185 LLVMExecutionEngineRef EE) {
186 LLVMAddModuleProvider(EE, MP);
187 return Val_unit;
188}
189
190/* llmoduleprovider -> ExecutionEngine.t -> llmodule */
191CAMLprim LLVMModuleRef llvm_ee_remove_mp(LLVMModuleProviderRef MP,
192 LLVMExecutionEngineRef EE) {
193 LLVMModuleRef RemovedModule;
194 char *Error;
195 if (LLVMRemoveModuleProvider(EE, MP, &RemovedModule, &Error))
196 llvm_raise(llvm_ee_error_exn, Error);
197 return RemovedModule;
198}
199
200/* string -> ExecutionEngine.t -> llvalue option */
201CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) {
202 CAMLparam1(Name);
203 CAMLlocal1(Option);
204 LLVMValueRef Found;
205 if (LLVMFindFunction(EE, String_val(Name), &Found))
206 CAMLreturn(Val_unit);
207 Option = alloc(1, 1);
208 Field(Option, 0) = Val_op(Found);
209 CAMLreturn(Option);
210}
211
212/* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */
213CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args,
214 LLVMExecutionEngineRef EE) {
215 unsigned NumArgs;
216 LLVMGenericValueRef Result, *GVArgs;
217 unsigned I;
218
219 NumArgs = Wosize_val(Args);
220 GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef));
221 for (I = 0; I != NumArgs; ++I)
222 GVArgs[I] = Genericvalue_val(Field(Args, I));
223
224 Result = LLVMRunFunction(EE, F, NumArgs, GVArgs);
225
226 free(GVArgs);
227 return alloc_generic_value(Result);
228}
229
230/* ExecutionEngine.t -> unit */
231CAMLprim value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) {
232 LLVMRunStaticConstructors(EE);
233 return Val_unit;
234}
235
236/* ExecutionEngine.t -> unit */
237CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) {
238 LLVMRunStaticDestructors(EE);
239 return Val_unit;
240}
241
242/* llvalue -> string array -> (string * string) array -> ExecutionEngine.t ->
243 int */
244CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F,
245 value Args, value Env,
246 LLVMExecutionEngineRef EE) {
247 CAMLparam2(Args, Env);
248 int I, NumArgs, NumEnv, EnvSize, Result;
249 const char **CArgs, **CEnv;
250 char *CEnvBuf, *Pos;
251
252 NumArgs = Wosize_val(Args);
253 NumEnv = Wosize_val(Env);
254
255 /* Build the environment. */
256 CArgs = (const char **) malloc(NumArgs * sizeof(char*));
257 for (I = 0; I != NumArgs; ++I)
258 CArgs[I] = String_val(Field(Args, I));
259
260 /* Compute the size of the environment string buffer. */
261 for (I = 0, EnvSize = 0; I != NumEnv; ++I) {
262 EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1;
263 EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1;
264 }
265
266 /* Build the environment. */
267 CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*));
268 CEnvBuf = (char*) malloc(EnvSize);
269 Pos = CEnvBuf;
270 for (I = 0; I != NumEnv; ++I) {
271 char *Name = String_val(Field(Field(Env, I), 0)),
272 *Value = String_val(Field(Field(Env, I), 1));
273 int NameLen = strlen(Name),
274 ValueLen = strlen(Value);
275
276 CEnv[I] = Pos;
277 memcpy(Pos, Name, NameLen);
278 Pos += NameLen;
279 *Pos++ = '=';
280 memcpy(Pos, Value, ValueLen);
281 Pos += ValueLen;
282 *Pos++ = '\0';
283 }
284 CEnv[NumEnv] = NULL;
285
286 Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv);
287
288 free(CArgs);
289 free(CEnv);
290 free(CEnvBuf);
291
292 CAMLreturn(Val_int(Result));
293}
294
295/* llvalue -> ExecutionEngine.t -> unit */
296CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F,
297 LLVMExecutionEngineRef EE) {
298 LLVMFreeMachineCodeForFunction(EE, F);
299 return Val_unit;
300}
301