Added a ;
[libfirm] / ir / be / bejavacoal.c
1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #ifdef WITH_LIBCORE
7 #include <libcore/lc_opts.h>
8 #include <libcore/lc_opts_enum.h>
9 #endif /* WITH_LIBCORE */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <jni.h>
14
15 #include "bejavacoal.h"
16
17 static char jar_file[256] = "/ben/hack/public/coal.jar";
18 static char cls_name[256] = "coalescing/mst/safe/Algo";
19
20 #ifdef WITH_LIBCORE
21 static const lc_opt_table_entry_t options[] = {
22         LC_OPT_ENT_STR      ("jar",  "jar file of the coalescer",                   jar_file, sizeof(jar_file)),
23         LC_OPT_ENT_STR      ("cls",  "name of the class providing the factory",     cls_name, sizeof(cls_name)),
24         { NULL }
25 };
26
27 void java_coal_register_options(lc_opt_entry_t *grp)
28 {
29         lc_opt_entry_t *jc_grp = lc_opt_get_grp(grp, "jc");
30         lc_opt_add_table(jc_grp, options);
31 }
32 #endif
33
34 typedef struct _jni_env_t {
35         JavaVM *jvm;
36         JNIEnv *jni;
37 } jni_env_t;
38
39 static int start_vm(jni_env_t *env, int argc, char *argv[])
40 {
41         int i;
42         long ret;
43         JavaVMInitArgs args;
44         JavaVMOption *opts;
45
46         memset(&args, 0, sizeof(args));
47         opts = malloc(argc * sizeof(opts[0]));
48         for(i = 0; i < argc; ++i) {
49                 opts[i].optionString = argv[i];
50                 opts[i].extraInfo    = NULL;
51         }
52
53         args.version  = JNI_VERSION_1_4;
54         args.nOptions = argc;
55         args.options  = opts;
56         args.ignoreUnrecognized = JNI_FALSE;
57
58         ret = JNI_CreateJavaVM(&env->jvm, (void **) &env->jni, &args);
59         free(opts);
60         if(ret == JNI_ERR)
61                 return 0;
62
63         return 1;
64 }
65
66 static void stop_vm(jni_env_t *env)
67 {
68         JavaVM *jvm = env->jvm;
69         (*jvm)->DetachCurrentThread(jvm);
70         (*jvm)->DestroyJavaVM(jvm);
71 }
72
73
74
75 static int jvm_inited = 0;
76 static jni_env_t env;
77
78 static void jvm_destroy_at_exit(void)
79 {
80         if(jvm_inited)
81                 stop_vm(&env);
82 }
83
84 static jni_env_t *get_jvm(void)
85 {
86
87         char cp_param[512];
88         char *args[1];
89
90         if(!jvm_inited) {
91                 snprintf(cp_param, sizeof(cp_param), "-Djava.class.path=%s", jar_file);
92                 args[0] = cp_param;
93                 start_vm(&env, sizeof(args) / sizeof(args[0]), args);
94                 jvm_inited = 1;
95                 atexit(jvm_destroy_at_exit);
96         }
97
98         return &env;
99 }
100
101 static void check(jni_env_t *env, const char *file, int line)
102 {
103         JNIEnv *jni = env->jni;
104         jboolean exc = (*jni)->ExceptionCheck(jni);
105         if(exc) {
106                 fprintf(stderr, "%s:%d: ", file, line);
107                 (*jni)->ExceptionDescribe(jni);
108                 (*jni)->ExceptionClear(jni);
109                 stop_vm(env);
110                 exit(1);
111         }
112 }
113
114 #define CHECK(env) check(env, __FILE__, __LINE__)
115
116
117
118 typedef struct _jni_env_t jni_env_t;
119
120
121 enum {
122         mth_add_int_edge,
123         mth_add_aff_edge,
124         mth_set_color,
125         mth_get_color,
126         mth_forbid_color,
127         mth_coalesce,
128         mth_dump,
129         mth_last
130 };
131
132 struct _mth_info_t {
133         const char *name;
134         const char *sig;
135 };
136
137 static const struct _mth_info_t mthis[mth_last] = {
138         { "addIntEdge",  "(II)V"                   }, /* public void addIntEdge(int, int); */
139         { "addAffEdge",  "(III)V"                  }, /* public void addAffEdge(int, int, int); */
140         { "setColor",    "(II)V"                   }, /* public void setColor(int, int); */
141         { "forbidColor", "(II)V"                   }, /* public void forbidColor(int, int); */
142         { "getColor",    "(I)I"                    }, /* public int getColor(int); */
143         { "coalesce",    "()V"                     }, /* public void coalesce(); */
144         { "dump",        "(Ljava/lang/String;)V"   }  /* public void dump(String); */
145 };
146
147 /* public static coalescing.Extern createExtern(java.lang.String, int, int, int); */
148 static const struct _mth_info_t mthi_factory = {
149         "createExtern", "(Ljava/lang/String;III)Lcoalescing/Extern;"
150 };
151
152 struct _java_coal_t {
153         jni_env_t *env;
154         jclass    cls;
155         jobject   obj;
156
157         jmethodID mth_ids[mth_last];
158 };
159
160 typedef struct _java_coal_t java_coal_t;
161
162 static void jc_call_void(java_coal_t *c, int mth_index, ...)
163 {
164         JNIEnv *jni   = c->env->jni;
165         jmethodID mid = c->mth_ids[mth_index];
166
167         va_list args;
168
169         va_start(args, mth_index);
170         (*jni)->CallVoidMethodV(jni, c->obj, mid, args);
171         CHECK(c->env);
172         va_end(args);
173 }
174
175 static int jc_call_int(java_coal_t *c, int mth_index, ...)
176 {
177         JNIEnv *jni   = c->env->jni;
178         jmethodID mid = c->mth_ids[mth_index];
179
180         int res;
181         va_list args;
182
183         va_start(args, mth_index);
184         res = (*jni)->CallIntMethodV(jni, c->obj, mid, args);
185         CHECK(c->env);
186         va_end(args);
187
188         return res;
189 }
190
191 java_coal_t *java_coal_init(const char *graph_name, int n_nodes, int n_regs, int dbg_level)
192 {
193         java_coal_t *c;
194         jni_env_t *env = get_jvm();
195         JNIEnv *jni = env->jni;
196         jmethodID fact;
197         jclass cls;
198         jstring str;
199         int i;
200
201         c = malloc(sizeof(c[0]));
202         memset(c, 0, sizeof(c[0]));
203         c->env = env;
204
205         /* Find the class we are are looking for. */
206         cls = (*jni)->FindClass(jni, cls_name);
207         CHECK(env);
208
209         /* Get the static factory method. */
210         fact = (*jni)->GetStaticMethodID(jni, cls, mthi_factory.name, mthi_factory.sig);
211         CHECK(env);
212
213         /* Call the factory. */
214         str = (*jni)->NewStringUTF(jni, graph_name);
215         CHECK(env);
216         c->obj = (*jni)->CallStaticObjectMethod(jni, cls, fact, str, n_nodes, n_regs, dbg_level);
217         CHECK(env);
218         c->cls = (*jni)->GetObjectClass(jni, c->obj);
219
220         /* Reference the created object. */
221         c->obj = (*jni)->NewGlobalRef(jni, c->obj);
222         CHECK(env);
223
224         /* Lookup the member methods of the object. */
225         for(i = 0; i < mth_last; ++i) {
226                 c->mth_ids[i] = (*jni)->GetMethodID(jni, c->cls, mthis[i].name, mthis[i].sig);
227                 CHECK(env);
228         }
229
230         return c;
231 }
232
233 void java_coal_destroy(java_coal_t *c) {
234         JNIEnv *jni = c->env->jni;
235         (*jni)->DeleteGlobalRef(jni, c->obj);
236         free(c);
237 }
238
239 void java_coal_add_int_edge(java_coal_t *c, int n, int m)
240 {
241         jc_call_void(c, mth_add_int_edge, (jint) n, (jint) m);
242 }
243
244 void java_coal_add_aff_edge(java_coal_t *c, int n, int m, int weight)
245 {
246         jc_call_void(c, mth_add_aff_edge, (jint) n, (jint) m, (jint) weight);
247 }
248
249 void java_coal_set_color(java_coal_t *c, int n, int col)
250 {
251         jc_call_void(c, mth_set_color, (jint) n, (jint) col);
252 }
253
254 void java_coal_forbid_color(java_coal_t *c, int n, int col)
255 {
256         jc_call_void(c, mth_forbid_color, (jint) n, (jint) col);
257 }
258
259 void java_coal_coalesce(java_coal_t *c)
260 {
261         jc_call_void(c, mth_coalesce);
262 }
263
264 void java_coal_dump(java_coal_t *c, const char *fn)
265 {
266         JNIEnv *jni   = c->env->jni;
267         jmethodID mid = c->mth_ids[mth_dump];
268         jstring str;
269
270         str = (*jni)->NewStringUTF(jni, fn);
271         CHECK(c->env);
272         (*jni)->CallVoidMethod(jni, c->obj, mid, str);
273         CHECK(c->env);
274 }
275
276 int java_coal_get_color(java_coal_t *c, int n)
277 {
278         return jc_call_int(c, mth_get_color, (jint) n);
279 }