Fix some Ocaml GC errors noticed upon review.
[oota-llvm.git] / bindings / ocaml / executionengine / executionengine_ocaml.c
1 /*===-- 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. */
29 static value llvm_ee_error_exn;
30
31 CAMLprim 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
37 static 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
54 static void llvm_finalize_generic_value(value GenVal) {
55   LLVMDisposeGenericValue(Genericvalue_val(GenVal));
56 }
57
58 static 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
67 static 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 */
74 CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) {
75   CAMLparam1(N);
76   CAMLreturn(alloc_generic_value(
77     LLVMCreateGenericValueOfFloat(Ty, Double_val(N))));
78 }
79
80 /* 'a -> t */
81 CAMLprim value llvm_genericvalue_of_value(value V) {
82   CAMLparam1(V);
83   CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V))));
84 }
85
86 /* Llvm.lltype -> int -> t */
87 CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) {
88   return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1));
89 }
90
91 /* Llvm.lltype -> int32 -> t */
92 CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) {
93   CAMLparam1(Int32);
94   CAMLreturn(alloc_generic_value(
95     LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32), 1)));
96 }
97
98 /* Llvm.lltype -> nativeint -> t */
99 CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) {
100   CAMLparam1(NatInt);
101   CAMLreturn(alloc_generic_value(
102     LLVMCreateGenericValueOfInt(Ty, Nativeint_val(NatInt), 1)));
103 }
104
105 /* Llvm.lltype -> int64 -> t */
106 CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) {
107   CAMLparam1(Int64);
108   CAMLreturn(alloc_generic_value(
109     LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64), 1)));
110 }
111
112 /* Llvm.lltype -> t -> float */
113 CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) {
114   CAMLparam1(GenVal);
115   CAMLreturn(copy_double(
116     LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal))));
117 }
118
119 /* t -> 'a */
120 CAMLprim value llvm_genericvalue_as_value(value GenVal) {
121   return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal)));
122 }
123
124 /* t -> int */
125 CAMLprim value llvm_genericvalue_as_int(value GenVal) {
126   assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value)
127          && "Generic value too wide to treat as an int!");
128   return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1));
129 }
130
131 /* t -> int32 */
132 CAMLprim value llvm_genericvalue_as_int32(value GenVal) {
133   CAMLparam1(GenVal);
134   assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32
135          && "Generic value too wide to treat as an int32!");
136   CAMLreturn(copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)));
137 }
138
139 /* t -> int64 */
140 CAMLprim value llvm_genericvalue_as_int64(value GenVal) {
141   CAMLparam1(GenVal);
142   assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64
143          && "Generic value too wide to treat as an int64!");
144   CAMLreturn(copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)));
145 }
146
147 /* t -> nativeint */
148 CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) {
149   CAMLparam1(GenVal);
150   assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value)
151          && "Generic value too wide to treat as a nativeint!");
152   CAMLreturn(copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1)));
153 }
154
155
156 /*--... Operations on execution engines ....................................--*/
157
158 /* llmoduleprovider -> ExecutionEngine.t */
159 CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleProviderRef MP) {
160   LLVMExecutionEngineRef Interp;
161   char *Error;
162   if (LLVMCreateExecutionEngine(&Interp, MP, &Error))
163     llvm_raise(llvm_ee_error_exn, Error);
164   return Interp;
165 }
166
167 /* llmoduleprovider -> ExecutionEngine.t */
168 CAMLprim LLVMExecutionEngineRef
169 llvm_ee_create_interpreter(LLVMModuleProviderRef MP) {
170   LLVMExecutionEngineRef Interp;
171   char *Error;
172   if (LLVMCreateInterpreter(&Interp, MP, &Error))
173     llvm_raise(llvm_ee_error_exn, Error);
174   return Interp;
175 }
176
177 /* llmoduleprovider -> ExecutionEngine.t */
178 CAMLprim LLVMExecutionEngineRef
179 llvm_ee_create_jit(LLVMModuleProviderRef MP) {
180   LLVMExecutionEngineRef JIT;
181   char *Error;
182   if (LLVMCreateJITCompiler(&JIT, MP, &Error))
183     llvm_raise(llvm_ee_error_exn, Error);
184   return JIT;
185 }
186
187 /* ExecutionEngine.t -> unit */
188 CAMLprim value llvm_ee_dispose(LLVMExecutionEngineRef EE) {
189   LLVMDisposeExecutionEngine(EE);
190   return Val_unit;
191 }
192
193 /* llmoduleprovider -> ExecutionEngine.t -> unit */
194 CAMLprim value llvm_ee_add_mp(LLVMModuleProviderRef MP,
195                               LLVMExecutionEngineRef EE) {
196   LLVMAddModuleProvider(EE, MP);
197   return Val_unit;
198 }
199
200 /* llmoduleprovider -> ExecutionEngine.t -> llmodule */
201 CAMLprim LLVMModuleRef llvm_ee_remove_mp(LLVMModuleProviderRef MP,
202                                          LLVMExecutionEngineRef EE) {
203   LLVMModuleRef RemovedModule;
204   char *Error;
205   if (LLVMRemoveModuleProvider(EE, MP, &RemovedModule, &Error))
206     llvm_raise(llvm_ee_error_exn, Error);
207   return RemovedModule;
208 }
209
210 /* string -> ExecutionEngine.t -> llvalue option */
211 CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) {
212   CAMLparam1(Name);
213   CAMLlocal1(Option);
214   LLVMValueRef Found;
215   if (LLVMFindFunction(EE, String_val(Name), &Found))
216     CAMLreturn(Val_unit);
217   Option = alloc(1, 1);
218   Field(Option, 0) = Val_op(Found);
219   CAMLreturn(Option);
220 }
221
222 /* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */
223 CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args,
224                                     LLVMExecutionEngineRef EE) {
225   unsigned NumArgs;
226   LLVMGenericValueRef Result, *GVArgs;
227   unsigned I;
228   
229   NumArgs = Wosize_val(Args);
230   GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef));
231   for (I = 0; I != NumArgs; ++I)
232     GVArgs[I] = Genericvalue_val(Field(Args, I));
233   
234   Result = LLVMRunFunction(EE, F, NumArgs, GVArgs);
235   
236   free(GVArgs);
237   return alloc_generic_value(Result);
238 }
239
240 /* ExecutionEngine.t -> unit */
241 CAMLprim value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) {
242   LLVMRunStaticConstructors(EE);
243   return Val_unit;
244 }
245
246 /* ExecutionEngine.t -> unit */
247 CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) {
248   LLVMRunStaticDestructors(EE);
249   return Val_unit;
250 }
251
252 /* llvalue -> string array -> (string * string) array -> ExecutionEngine.t ->
253    int */
254 CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F,
255                                             value Args, value Env,
256                                             LLVMExecutionEngineRef EE) {
257   CAMLparam2(Args, Env);
258   int I, NumArgs, NumEnv, EnvSize, Result;
259   const char **CArgs, **CEnv;
260   char *CEnvBuf, *Pos;
261   
262   NumArgs = Wosize_val(Args);
263   NumEnv = Wosize_val(Env);
264   
265   /* Build the environment. */
266   CArgs = (const char **) malloc(NumArgs * sizeof(char*));
267   for (I = 0; I != NumArgs; ++I)
268     CArgs[I] = String_val(Field(Args, I));
269   
270   /* Compute the size of the environment string buffer. */
271   for (I = 0, EnvSize = 0; I != NumEnv; ++I) {
272     EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1;
273     EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1;
274   }
275   
276   /* Build the environment. */
277   CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*));
278   CEnvBuf = (char*) malloc(EnvSize);
279   Pos = CEnvBuf;
280   for (I = 0; I != NumEnv; ++I) {
281     char *Name  = String_val(Field(Field(Env, I), 0)),
282          *Value = String_val(Field(Field(Env, I), 1));
283     int NameLen  = strlen(Name),
284         ValueLen = strlen(Value);
285     
286     CEnv[I] = Pos;
287     memcpy(Pos, Name, NameLen);
288     Pos += NameLen;
289     *Pos++ = '=';
290     memcpy(Pos, Value, ValueLen);
291     Pos += ValueLen;
292     *Pos++ = '\0';
293   }
294   CEnv[NumEnv] = NULL;
295   
296   Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv);
297   
298   free(CArgs);
299   free(CEnv);
300   free(CEnvBuf);
301   
302   CAMLreturn(Val_int(Result));
303 }
304
305 /* llvalue -> ExecutionEngine.t -> unit */
306 CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F,
307                                          LLVMExecutionEngineRef EE) {
308   LLVMFreeMachineCodeForFunction(EE, F);
309   return Val_unit;
310 }
311