* configure.ac: Added tests for python.
[cacao.git] / src / vm / jit / python.c
1 /* src/vm/jit/python.c - Python pass
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Note: this code is currently alpha and needs to be documented.
26
27    This code wraps the jitdata structure into a python object and
28    makes it possible to implement a compiler pass as python function.
29
30    The wrapping of cacao types to python objects is meant to be easy and
31    straight-forward.
32  
33    Cacao structs a wrapped into a python ``wrapper'' object, the state of 
34    which consists of:
35
36     * A void pointer.
37         * A pointer to a class function (see class_func), which implements the
38           object's behaviour.
39
40    Arrays and collection-like data structures are wrapped into a python
41    ``iterator'' object, the state of wich consists of:
42
43     * A void pointer.
44         * Another void pointer that is the cursor.
45         * A pointer to a iterator function (see iterator_func) which implements
46           the iterator's behaviour.
47
48    Because in python field names are identified as strings, to avoid a lot
49    of string comparisons, we translate the field as early as possible into 
50    an integer constant. This is achieved using the field_map array.
51
52    We could have used a wrapper generator like swig, but we don't want to 
53    wrap the rather low level C api to python 1:1. When wrappig stuff, try
54    to do it rather high level and in a pythonic way. Examples:
55
56     * Bad: instruction.flags and cacao.FLAG_UNRESOLVED == 0
57         * Good: instruction.is_unresolved
58         * Bad: for i in range(0, bb.icount): instr = bb.instructions[i]
59         * Good: for instr in bb.instructions
60 */
61
62 #include <Python.h>
63
64 #include "vm/jit/python.h"
65
66 /*
67  * Defs
68  */
69
70 union class_arg {
71         struct {
72                 int field;
73                 PyObject **result;
74         } get;
75         struct {
76                 int field;
77                 PyObject *value;
78         } set;
79 };
80
81 typedef union class_arg class_arg;
82
83 enum class_op {
84         SET_FIELD,
85         GET_FIELD
86 };
87
88 typedef enum class_op class_op;
89
90 typedef int(*class_func)(void *, class_op, class_arg *);
91 #define CLASS_FUNC(name) int name(void *vp, class_op op, class_arg *arg)
92
93 struct iterator_state {
94         void *data;
95         void *pos;
96 };
97
98 union iterator_arg {
99         struct {
100                 PyObject **result;
101         } get;
102         struct {
103                 unsigned int index;
104                 PyObject **result;
105         } subscript;
106         int length;
107 };
108
109 typedef union iterator_arg iterator_arg;
110
111 typedef struct iterator_state iterator_state;
112
113 enum iterator_op {
114         ITERATOR_INIT,
115         ITERATOR_GET,
116         ITERATOR_FORWARD,
117         ITERATOR_END,
118         ITERATOR_SUBSCRIPT,
119         ITERATOR_LENGTH
120 };
121
122 typedef enum iterator_op iterator_op;
123
124 typedef int(*iterator_func)(iterator_op op, iterator_state *state, iterator_arg *arg);
125 #define ITERATOR_FUNC(name) int name (iterator_op op, iterator_state *state, iterator_arg *arg)
126 #define ITERATOR_SUBSCRIPT_CHECK(end) if (arg->subscript.index >= (end)) return -1
127
128 struct field_map_entry {
129         const char *name;
130         int tag;
131 };
132
133 typedef struct field_map_entry field_map_entry;
134
135 enum field {
136         F_BASIC_BLOCKS,
137         F_CALL_RETURN_TYPE,
138         F_CALL_ARGS,
139         F_CLASSREF,
140         F_DST,
141         F_DESCRIPTOR,
142         F_EXCEPTION_HANDLER,
143         F_FIELD_TYPE,
144         F_FIELD,
145         F_INSTRUCTIONS,
146         F_IS_CLASS_CONSTANT,
147         F_IS_UNRESOLVED,
148         F_LOCAL_METHODINFO,
149         F_KLASS,
150         F_LINE,
151         F_LOCAL_MAP,
152         F_METHOD,
153         F_NAME,
154         F_NAME_EX,
155         F_NR,
156         F_OFFSET,
157         F_OPCODE,
158         F_OPCODE_EX,
159         F_PARAM_TYPES,
160         F_PREDECESSORS,
161         F_REACHED,
162         F_RETURN_TYPE,
163         F_S1,
164         F_S2,
165         F_S3,
166         F_SUCCESSORS,
167         F_TYPE,
168         F_UNRESOLVED_FIELD,
169         F_VARS
170 };
171
172 /* Keep it soreted alphabetically, so we can support binary search in future. */
173 struct field_map_entry field_map[] = {
174         { "basic_blocks", F_BASIC_BLOCKS },
175         { "call_return_type", F_CALL_RETURN_TYPE },
176         { "call_args", F_CALL_ARGS },
177         { "classref", F_CLASSREF },
178         { "dst", F_DST },
179         { "descriptor", F_DESCRIPTOR },
180         { "exception_handler", F_EXCEPTION_HANDLER },
181         { "field", F_FIELD },
182         { "field_type", F_FIELD_TYPE },
183         { "instructions", F_INSTRUCTIONS },
184         { "is_unresolved", F_IS_UNRESOLVED },
185         { "is_class_constant", F_IS_CLASS_CONSTANT },
186         { "klass", F_KLASS },
187         { "line", F_LINE },
188         { "local_map", F_LOCAL_MAP },
189         { "local_methodinfo", F_LOCAL_METHODINFO },
190         { "method", F_METHOD },
191         { "name", F_NAME },
192         { "name_ex", F_NAME_EX },
193         { "nr", F_NR },
194         { "offset", F_OFFSET },
195         { "opcode", F_OPCODE },
196         { "opcode_ex", F_OPCODE_EX },
197         { "param_types", F_PARAM_TYPES },
198         { "predecessors", F_PREDECESSORS },
199         { "reached", F_REACHED },
200         { "return_type", F_RETURN_TYPE },
201         { "s1", F_S1 },
202         { "s2", F_S2 },
203         { "s3", F_S3 },
204         { "successors", F_SUCCESSORS },
205         { "type", F_TYPE },
206         { "unresolved_field", F_UNRESOLVED_FIELD },
207         { "vars", F_VARS },
208         { NULL, 0 }
209 };
210
211 int field_find(const char *key) {
212         field_map_entry *it;
213
214         for (it = field_map; it->name; ++it) {
215                 if (strcmp(it->name, key) == 0) {
216                         return it->tag;
217                 }
218         }
219
220         return -1;
221 }
222
223 /*
224  * Python
225  */
226
227 struct wrapper {
228         PyObject_HEAD
229         void *data;
230         class_func func;
231 };
232
233 typedef struct wrapper wrapper;
234
235 PyObject *wrapper_getattr(wrapper *w, PyObject *fld) {
236         class_arg arg;
237         PyObject *result;
238
239         arg.get.field = field_find(PyString_AsString(fld));
240         if (arg.get.field == -1) {
241                 return NULL;
242         }
243
244         arg.get.result = &result;
245
246         if (w->func(w->data, GET_FIELD, &arg) == -1) {
247                 return NULL;
248         }
249
250         return result;
251 }
252
253 int wrapper_setattr(wrapper *w, PyObject *fld, PyObject *value) {
254         class_arg arg;
255
256         arg.set.field = field_find(PyString_AsString(fld));
257         if (arg.set.field == -1) {
258                 return -1;
259         }
260         arg.set.value = value;
261
262         if (w->func(w->data, SET_FIELD, &arg) == -1) {
263                 return -1;
264         }
265
266         return 0;
267 }
268
269 extern PyTypeObject wrapper_type;
270
271 int wrapper_compare(wrapper *a, wrapper *b) {
272         if (PyObject_TypeCheck(b, &wrapper_type)) {
273                 if (a->data < b->data) {
274                         return -1;
275                 } else if (a->data > b->data) {
276                         return 1;
277                 } else {
278                         return 0;
279                 }
280         } else {
281                 /* If classes differ, compare classes */
282                 return PyObject_Compare(a->ob_type, b->ob_type);
283         }
284 }
285
286 long wrapper_hash(wrapper *a) {
287         return (long)a->data;
288 }
289
290 PyTypeObject wrapper_type = {
291         PyObject_HEAD_INIT(NULL)
292         0, /* ob_size */
293         "wrapper", /* tp_name */
294         sizeof(wrapper), /* tp_basicsize */
295         0, /* tp_itemsize */
296         0, /* tp_dealloc */
297         0, /* tp_print */
298         0, /* tp_getattr */
299         0, /* tp_setattr */
300         wrapper_compare, /* tp_compare */
301         0, /* tp_repr */
302         0, /* tp_as_number */
303         0, /* tp_as_sequence */
304         0, /* tp_as_mapping */
305         wrapper_hash, /* tp_hash */
306         0, /* tp_call */
307         0, /* tp_str */
308         wrapper_getattr, /* tp_getattro */
309         wrapper_setattr, /* tp_setattro */
310         0, /* tp_as_buffer */
311         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
312         0, /* tp_doc */
313         0, /* tp_traverse */
314         0, /* tp_clear */
315         0, /* tp_richcompare */
316         0, /* tp_weaklistoffset */
317         0, /* tp_iter */
318         0, /* tp_iternext */
319         0, /* tp_methods */
320         0, /* tp_members */
321         0, /* tp_getset */
322         0, /* tp_base */
323         0, /* tp_dict */
324         0, /* tp_descr_get */
325         0, /* tp_descr_set */
326         0, /* tp_dictoffset */
327         0, /* tp_init */
328         0, /* tp_alloc */
329         PyType_GenericNew, /* tp_new */
330 };
331
332 struct iterator {
333         PyObject_HEAD
334         iterator_func func;
335         iterator_state state;
336 };
337
338 typedef struct iterator iterator;
339
340 PyObject *iterator_iter(struct iterator *it) {
341         Py_INCREF(it);
342         return (PyObject *)it;
343 }
344
345 PyObject *iterator_iternext(struct iterator *it) {
346         PyObject *ret;
347         iterator_arg arg;
348
349         if (it->func(ITERATOR_END, &it->state, NULL)) {
350                 return NULL;
351         } else {
352                 arg.get.result = &ret;
353                 it->func(ITERATOR_GET, &it->state, &arg);
354                 it->func(ITERATOR_FORWARD, &it->state, NULL);
355                 return ret;
356         }
357 }
358
359 PyObject *iterator_getitem(struct iterator *it, PyObject* item) {
360         iterator_arg arg;
361         PyObject *ret;
362
363         if (PyInt_Check(item)) {
364                 arg.subscript.index = PyInt_AS_LONG(item);
365                 arg.subscript.result = &ret;
366                 if (index < 0) { 
367                         return NULL;
368                 } else if (it->func(ITERATOR_SUBSCRIPT, &it->state, &arg) != -1) {
369                         return ret;
370                 } else {
371                         return NULL;
372                 }
373         } else {
374                 return NULL;
375         }
376 }
377
378 int iterator_length(struct iterator *it) {
379         iterator_arg arg;
380         if (it->func(ITERATOR_LENGTH, &it->state, &arg) == -1) {
381                 return -1;
382         } else {
383                 return arg.length;
384         }
385 }
386
387 PyMappingMethods iterator_mapping = {
388         iterator_length,
389         iterator_getitem,
390         0
391 };
392
393 PyTypeObject iterator_type = {
394         PyObject_HEAD_INIT(NULL)
395         0, /* ob_size */
396         "iterator", /* tp_name */
397         sizeof(iterator), /* tp_basicsize */
398         0, /* tp_itemsize */
399         0, /* tp_dealloc */
400         0, /* tp_print */
401         0, /* tp_getattr */
402         0, /* tp_setattr */
403         0, /* tp_compare */
404         0, /* tp_repr */
405         0, /* tp_as_number */
406         0, /* tp_as_sequence */
407         &iterator_mapping, /* tp_as_mapping */
408         0, /* tp_hash */
409         0, /* tp_call */
410         0, /* tp_str */
411         0, /* tp_getattro */
412         0, /* tp_setattro */
413         0, /* tp_as_buffer */
414         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
415         0, /* tp_doc */
416         0, /* tp_traverse */
417         0, /* tp_clear */
418         0, /* tp_richcompare */
419         0, /* tp_weaklistoffset */
420         iterator_iter, /* tp_iter */
421         iterator_iternext, /* tp_iternext */
422         0, /* tp_methods */
423         0, /* tp_members */
424         0, /* tp_getset */
425         0, /* tp_base */
426         0, /* tp_dict */
427         0, /* tp_descr_get */
428         0, /* tp_descr_set */
429         0, /* tp_dictoffset */
430         0, /* tp_init */
431         0, /* tp_alloc */
432         PyType_GenericNew, /* tp_new */
433 };
434
435 /*
436  * Utils
437  */
438
439 int set_int(int *p, PyObject *o) {
440         if (PyInt_Check(o)) {
441                 *p = PyInt_AsLong(o);   
442                 return 0;
443         } else {
444                 return -1;
445         }
446 }
447
448 int get_int(PyObject **o, int p) {
449         *o = Py_BuildValue("i", p);
450         return 0;
451 }
452
453 int get_string(PyObject **o, const char *str) {
454         *o = PyString_FromString(str);
455         return 0;
456 }
457
458 int get_obj(PyObject **res, class_func f, void *p) {
459         if (p == NULL) {
460                 return get_none(res);
461         } else {
462                 PyObject *o = PyObject_CallObject((PyObject *)&wrapper_type, NULL);
463                 struct wrapper * w = (struct wrapper *)o;
464                 w->func = f;
465                 w->data = p;
466                 *res = o;
467                 return 0;
468         }
469 }
470
471 int get_true(PyObject **res) {
472         Py_INCREF(Py_True);
473         *res = Py_True;
474         return 0;
475 }
476
477 int get_false(PyObject **res) {
478         Py_INCREF(Py_False);
479         *res = Py_False;
480         return 0;
481 }
482
483 int get_none(PyObject **res) {
484         Py_INCREF(Py_None);
485         *res = Py_None;
486         return 0;
487 }
488
489 int get_bool(PyObject **res, int cond) {
490         return cond ? get_true(res) : get_false(res);
491 }
492         
493 int get_iter(PyObject **res, iterator_func f, void *p) {
494         PyObject *o = PyObject_CallObject((PyObject *)&iterator_type, NULL);
495         struct iterator * it = (struct iterator *)o;
496         it->func = f;
497         it->state.data = p;
498         f(ITERATOR_INIT, &it->state, NULL);
499         *res = o;
500         return 0;
501 }
502
503 int add_const(PyObject *module, const char *name, int value) {
504         PyObject *pyvalue = PyInt_FromLong(value);
505         if (pyvalue != NULL) {
506                 PyModule_AddObject(module, name, pyvalue);
507         }
508 }
509
510 /*
511  * Implemnetation
512  */
513
514 CLASS_FUNC(basicblock_func);
515 CLASS_FUNC(classinfo_func);
516 CLASS_FUNC(constant_classref_func);
517 CLASS_FUNC(methodinfo_func);
518
519 static inline methoddesc *instruction_call_site(instruction *iptr) {
520         if (iptr->opc == ICMD_BUILTIN) {
521                 return iptr->sx.s23.s3.bte->md;
522         } else if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
523                 return iptr->sx.s23.s3.um->methodref->parseddesc.md;
524         } else {
525                 return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
526         }
527 }
528
529 ITERATOR_FUNC(call_args_iter_func) {
530         instruction *iptr = (instruction *)state->data;
531         switch (op) {
532                 case ITERATOR_INIT:
533                         state->pos = iptr->sx.s23.s2.args;
534                         return 0;
535                 case ITERATOR_LENGTH:
536                         arg->length = instruction_call_site(iptr)->paramcount;
537                         return 0;
538                 case ITERATOR_GET:
539                         return get_int(arg->get.result, *(int *)state->pos);
540                 case ITERATOR_END:
541                         return state->pos == (iptr->sx.s23.s2.args + instruction_call_site(iptr)->paramcount);
542                 case ITERATOR_FORWARD:
543                         state->pos = ((int *)state->pos) + 1;
544                         return 0;
545                 case ITERATOR_SUBSCRIPT:
546                         ITERATOR_SUBSCRIPT_CHECK(instruction_call_site(iptr)->paramcount);
547                         return get_int(arg->subscript.result, iptr->sx.s23.s2.args[arg->subscript.index]);
548         }
549         return -1;
550 }
551
552 CLASS_FUNC(fieldinfo_func) {
553         fieldinfo *fi = (fieldinfo *)vp;
554
555         switch (op) {
556                 case GET_FIELD:
557                         switch (arg->get.field) {
558                                 case F_TYPE:
559                                         return get_int(arg->get.result, fi->type);
560                                 case F_OFFSET:
561                                         return get_int(arg->get.result, fi->offset);
562                                 case F_NAME:
563                                         return get_string(arg->get.result, fi->name->text);
564                                 case F_KLASS:
565                                         return get_obj(arg->get.result, classinfo_func, fi->class);
566                         }
567         }
568
569         return -1;
570 }
571
572 CLASS_FUNC(unresolved_field_func) {
573         unresolved_field *uf = (unresolved_field *)vp;
574         switch (op) {
575                 case GET_FIELD:
576                         switch (arg->get.field) {
577                                 case F_NAME:
578                                         return get_string(arg->get.result, uf->fieldref->name->text);
579                                 case F_CLASSREF:
580                                         if (IS_FMIREF_RESOLVED(uf->fieldref)) {
581                                                 return get_none(arg->get.result);
582                                         } else {
583                                                 return get_obj(arg->get.result, constant_classref_func, uf->fieldref->p.classref);
584                                         }
585                                 case F_DESCRIPTOR:
586                                         return get_string(arg->get.result, uf->fieldref->descriptor->text);
587                                 case F_FIELD:
588                                         if (IS_FMIREF_RESOLVED(uf->fieldref)) {
589                                                 return get_obj(arg->get.result, fieldinfo_func, uf->fieldref->p.field);
590                                         } else {
591                                                 return get_none(arg->get.result);
592                                         }
593                                 case F_IS_UNRESOLVED:
594                                         return get_bool(arg->get.result, !IS_FMIREF_RESOLVED(uf->fieldref));
595                         }
596         }
597         return -1;
598 }
599
600 CLASS_FUNC(instruction_func) {
601
602         instruction *iptr = (instruction *)vp;
603
604         switch (op) {
605                 case GET_FIELD:
606                         switch (arg->get.field) {
607                                 case F_OPCODE:
608                                         return get_int(arg->get.result, iptr->opc);
609                                 case F_OPCODE_EX:
610                                         if (iptr->opc == ICMD_BUILTIN) {
611                                                 return get_int(arg->get.result, iptr->sx.s23.s3.bte->opcode);
612                                         } else {
613                                                 return get_int(arg->get.result, iptr->opc);
614                                         }
615                                 case F_NAME:
616                                         return get_string(arg->get.result, icmd_table[iptr->opc].name);
617                                 case F_NAME_EX:
618                                         if (iptr->opc == ICMD_BUILTIN) {
619                                                 return get_string(arg->get.result, icmd_table[iptr->sx.s23.s3.bte->opcode].name);
620                                         } else {
621                                                 return get_string(arg->get.result, icmd_table[iptr->opc].name);
622                                         }
623                                 case F_S1:
624                                         return get_int(arg->get.result, iptr->s1.varindex);
625                                 case F_S2:
626                                         return get_int(arg->get.result, iptr->sx.s23.s2.varindex);
627                                 case F_S3:
628                                         return get_int(arg->get.result, iptr->sx.s23.s3.varindex);
629                                 case F_DST:
630                                         return get_int(arg->get.result, iptr->dst.varindex);
631                                 case F_CALL_RETURN_TYPE:
632                                         return get_int(arg->get.result, instruction_call_site(iptr)->returntype.type);
633                                 case F_CALL_ARGS:
634                                         return get_iter(arg->get.result, call_args_iter_func, iptr);    
635                                 case F_IS_UNRESOLVED:
636                                         return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_UNRESOLVED);
637                                 case F_IS_CLASS_CONSTANT:
638                                         return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_CLASS);
639                                 case F_KLASS:
640                                         return get_obj(arg->get.result, classinfo_func, iptr->sx.val.c.cls);
641                                 case F_CLASSREF:
642                                         return get_obj(arg->get.result, constant_classref_func, iptr->sx.val.c.ref);
643                                 case F_LOCAL_METHODINFO:
644                                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
645                                                 return get_none(arg->get.result);
646                                         } else {        
647                                                 return get_obj(arg->get.result, methodinfo_func, 
648                                                         iptr->sx.s23.s3.fmiref->p.method);
649                                         }
650                                 case F_FIELD_TYPE:
651                                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
652                                                 return get_int(arg->get.result,
653                                                         iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type);
654                                         } else {
655                                                 return get_int(arg->get.result,
656                                                         iptr->sx.s23.s3.fmiref->p.field->type);
657                                         }
658                                 case F_FIELD:
659                                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
660                                                 return get_none(arg->get.result);
661                                         } else {
662                                                 return get_obj(arg->get.result, fieldinfo_func, iptr->sx.s23.s3.fmiref->p.field);
663                                         }
664                                         break;
665                                 case F_UNRESOLVED_FIELD:
666                                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
667                                                 return get_obj(arg->get.result, unresolved_field_func, iptr->sx.s23.s3.uf);
668                                         } else {
669                                                 return get_none(arg->get.result);
670                                         }
671                                         break;
672                                 case F_LINE:
673                                         return get_int(arg->get.result, iptr->line);
674                         }
675         }
676
677         return -1;
678 }
679
680 ITERATOR_FUNC(predecessors_iter_func) {
681         basicblock *bptr = (basicblock *)state->data;
682
683         switch (op) {
684                 case ITERATOR_INIT:
685                         state->pos = bptr->predecessors;
686                         return 0;
687                 case ITERATOR_GET:
688                         return get_obj(arg->get.result, basicblock_func, *(basicblock **)state->pos);
689                 case ITERATOR_END:
690                         return 
691                                 (state->pos == (bptr->predecessors + bptr->predecessorcount)) ||
692                                 (bptr->predecessorcount < 0);
693                 case ITERATOR_FORWARD:
694                         state->pos = ((basicblock **)state->pos) + 1;
695                         return 0;
696         }
697
698         return -1;
699 }
700
701 ITERATOR_FUNC(successors_iter_func) {
702         basicblock *bptr = (basicblock *)state->data;
703
704         switch (op) {
705                 case ITERATOR_INIT:
706                         state->pos = bptr->successors;
707                         return 0;
708                 case ITERATOR_GET:
709                         return get_obj(arg->get.result, basicblock_func, *(basicblock **)state->pos);
710                 case ITERATOR_END:
711                         return 
712                                 (state->pos == (bptr->successors + bptr->successorcount)) || 
713                                 (bptr->successorcount < 0);
714                 case ITERATOR_FORWARD:
715                         state->pos = ((basicblock **)state->pos) + 1;
716                         return 0;
717         }
718
719         return  -1;
720 }
721
722 ITERATOR_FUNC(instruction_iter_func) {
723         basicblock *bptr = (basicblock *)state->data;
724
725         switch (op) {
726                 case ITERATOR_INIT:
727                         state->pos = bptr->iinstr;
728                         return 0;
729                 case ITERATOR_GET:
730                         return get_obj(arg->get.result, instruction_func, state->pos);
731                 case ITERATOR_FORWARD:
732                         state->pos = ((instruction *)state->pos) + 1;
733                         return 0;
734                 case ITERATOR_END:
735                         return state->pos == (bptr->iinstr + bptr->icount);
736                 case ITERATOR_SUBSCRIPT:
737                         ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
738                         return get_obj(arg->subscript.result, instruction_func, bptr->iinstr + arg->subscript.index);
739                 case ITERATOR_LENGTH:
740                         arg->length = bptr->icount;
741                         return 0;
742         }
743         return -1;
744 }
745
746 CLASS_FUNC(basicblock_func) {
747         basicblock *bptr = (basicblock *)vp;
748
749         switch (op) {
750                 case GET_FIELD:
751                         switch (arg->get.field) {
752                                 case F_INSTRUCTIONS:
753                                         return get_iter(arg->get.result, instruction_iter_func, bptr);
754                                 case F_NR:
755                                         return get_int(arg->get.result, bptr->nr);
756                                 case F_PREDECESSORS:
757                                         return get_iter(arg->get.result, predecessors_iter_func, bptr);
758                                 case F_SUCCESSORS:
759                                         return get_iter(arg->get.result, successors_iter_func, bptr);
760                                 case F_REACHED:
761                                         return get_bool(arg->get.result, bptr->flags >= BBREACHED);
762                                 case F_EXCEPTION_HANDLER:
763                                         return get_bool(arg->get.result, bptr->type == BBTYPE_EXH);
764                         }
765         }
766
767         return -1;
768 }
769
770 ITERATOR_FUNC(basicblocks_iter_func) {
771         jitdata *jd = (jitdata *)state->data;
772
773         switch (op) {
774                 case ITERATOR_INIT:
775                         state->pos = jd->basicblocks;
776                         return 0;       
777                 case ITERATOR_GET:
778                         return get_obj(arg->get.result, basicblock_func, state->pos);
779                 case ITERATOR_FORWARD:
780                         state->pos = ((basicblock *)(state->pos))->next;
781                         return 0;
782                 case ITERATOR_END:
783                         return (state->pos == NULL);
784                 case ITERATOR_SUBSCRIPT:
785                         if (arg->subscript.index == 0 && jd->basicblocks != NULL) {
786                                 return get_obj(arg->subscript.result, basicblock_func, jd->basicblocks);
787                         } else {
788                                 return -1;
789                         }
790         }
791
792         return -1;
793 }
794
795 CLASS_FUNC(classinfo_func) {
796         classinfo *c = (classinfo *)vp;
797         switch (op) {
798                 case GET_FIELD:
799                         switch (arg->get.field) {
800                                 case F_NAME:
801                                         return get_string(arg->get.result, c->name->text);
802                         }
803         }
804         return -1;
805 }
806
807 CLASS_FUNC(constant_classref_func) {
808         constant_classref *cr = (constant_classref *)vp;
809         switch (op) {
810                 case GET_FIELD:
811                         switch (arg->get.field) {
812                                 case F_NAME:
813                                         return get_string(arg->get.result, cr->name->text);
814                         }
815         }
816         return -1;
817 }
818
819 ITERATOR_FUNC(param_types_iter_func) {
820         methodinfo *m = (methodinfo *)state->data;
821
822         switch (op) {
823                 case ITERATOR_INIT:
824                         state->pos = m->parseddesc->paramtypes;
825                         return 0;
826                 case ITERATOR_END:
827                         return state->pos == (m->parseddesc->paramtypes + m->parseddesc->paramcount);
828                 case ITERATOR_FORWARD:
829                         state->pos = ((typedesc *)state->pos) + 1;
830                         return 0;
831                 case ITERATOR_GET:
832                         return get_int(arg->get.result, ((typedesc *)state->pos)->type);
833                 case ITERATOR_LENGTH:
834                         arg->length = m->parseddesc->paramcount;
835                         return 0;
836                 case ITERATOR_SUBSCRIPT:
837                         ITERATOR_SUBSCRIPT_CHECK(m->parseddesc->paramcount);
838                         return get_int(arg->subscript.result, m->parseddesc->paramtypes[arg->subscript.index].type);
839         }
840
841         return -1;
842 }
843
844 CLASS_FUNC(methodinfo_func) {
845         methodinfo *m = (methodinfo *)vp;
846         switch (op) {
847                 case GET_FIELD:
848                         switch (arg->get.field) {
849                                 case F_NAME:
850                                         return get_string(arg->get.result, m->name->text);
851                                 case F_KLASS:
852                                         return get_obj(arg->get.result, classinfo_func, m->class);
853                                 case F_PARAM_TYPES:
854                                         return get_iter(arg->get.result, param_types_iter_func, m);
855                                 case F_RETURN_TYPE:
856                                         return get_int(arg->get.result, m->parseddesc->returntype.type);
857                         }
858         }
859         return -1;
860 }
861
862
863 CLASS_FUNC(varinfo_func) {
864         varinfo *var = (varinfo *)vp;
865         switch (op) {
866                 case GET_FIELD:
867                         switch (arg->get.field) {
868                                 case F_TYPE:
869                                         return get_int(arg->get.result, var->type);
870                         }
871         }
872         return -1;
873 }
874
875 ITERATOR_FUNC(vars_func) {
876         jitdata *jd = (jitdata *)state->data;
877         switch (op) {
878                 case ITERATOR_INIT:
879                         state->pos = jd->var;
880                         return 0;
881                 case ITERATOR_FORWARD:
882                         state->pos = ((varinfo *)state->pos) + 1;
883                         return 0;
884                 case ITERATOR_END:
885                         return state->pos == (jd->var + jd->varcount);
886                 case ITERATOR_GET:
887                         return get_obj(arg->get.result, varinfo_func, state->pos);
888                 case ITERATOR_LENGTH:
889                         arg->length = jd->varcount;
890                         return 0;
891                 case ITERATOR_SUBSCRIPT:
892                         ITERATOR_SUBSCRIPT_CHECK(jd->varcount);
893                         return get_obj(arg->subscript.result, varinfo_func, jd->var + arg->subscript.index);
894         }
895         return -1;
896 }
897
898 ITERATOR_FUNC(local_map_2_iter_func) {
899         int *arr = (int *)state->data;
900         switch (op) {
901                 case ITERATOR_SUBSCRIPT:
902                         ITERATOR_SUBSCRIPT_CHECK(5);
903                         return get_int(arg->subscript.result, arr[arg->subscript.index]);
904                 case ITERATOR_LENGTH:
905                         arg->length = 5;
906                         return 0;
907         }
908         return -1;
909 }
910
911 ITERATOR_FUNC(local_map_iter_func) {
912         jitdata *jd = (jitdata *)state->data;
913         switch (op) {
914                 case ITERATOR_SUBSCRIPT:
915                         /* todo ITERATOR_SUBSCRIPT_CHECK(); */
916                         return get_iter(arg->subscript.result, local_map_2_iter_func, 
917                                 jd->local_map + (5 * arg->subscript.index));
918         }
919         return -1;
920 }
921
922 CLASS_FUNC(jd_func) {
923         jitdata *jd = (jitdata *)vp;
924
925         switch (op) {
926                 case GET_FIELD:
927                         switch (arg->get.field) {
928                                 case F_BASIC_BLOCKS:
929                                         return get_iter(arg->get.result, basicblocks_iter_func, jd);
930                                 case F_METHOD:
931                                         return get_obj(arg->get.result, methodinfo_func, jd->m);
932                                 case F_VARS:
933                                         return get_iter(arg->get.result, vars_func, jd);
934                                 case F_LOCAL_MAP:
935                                         return get_iter(arg->get.result, local_map_iter_func, jd);
936                         }
937         }
938
939         return -1;
940 }
941
942 void constants(PyObject *m) {
943         char buf[32];
944         char *pos;
945         int i;
946
947         /* icmds */
948
949         for (i = 0; i < sizeof(icmd_table) / sizeof(icmd_table[0]); ++i) {
950                 snprintf(buf, sizeof(buf), "ICMD_%s", icmd_table[i].name);
951                 pos = strchr(buf, ' ');
952                 if (pos != NULL) {
953                         *pos = '\0';
954                 }
955                 add_const(m, buf, i);
956         }
957
958 #       define c(x) add_const(m, #x, x)
959
960         /* types */
961
962         c(TYPE_INT);
963         c(TYPE_LNG);
964         c(TYPE_ADR);
965         c(TYPE_FLT);
966         c(TYPE_DBL);
967         c(TYPE_VOID);
968         c(UNUSED);
969
970 #       undef c
971 }
972
973 /*
974  * Pythonpass
975  */
976
977 void pythonpass_init() {
978         PyObject *m;
979         
980         Py_Initialize();
981         PyEval_InitThreads();
982
983         if (PyType_Ready(&wrapper_type) < 0) return;
984         if (PyType_Ready(&iterator_type) < 0) return;
985
986         m = Py_InitModule3("cacao", NULL, NULL);
987         if (m != NULL) {
988                 constants(m);
989         }
990
991 }
992
993 void pythonpass_cleanup() {
994         Py_Finalize();
995 }
996
997 int pythonpass_run(jitdata *jd, const char *module, const char *function) {
998         PyObject *pymodname = NULL;
999         PyObject *pymod = NULL;
1000         PyObject *pydict = NULL;
1001         PyObject *pyfunc = NULL;
1002         PyObject *pyargs = NULL;
1003         PyObject *pyret = NULL;
1004         PyObject *pyarg = NULL;
1005         int success = 0;
1006
1007         pymodname = PyString_FromString(module);
1008         pymod = PyImport_Import(pymodname);
1009
1010         if (pymod != NULL) {
1011                 pydict = PyModule_GetDict(pymod);
1012                 pyfunc = PyDict_GetItemString(pydict, function);
1013                 if (pyfunc != NULL && PyCallable_Check(pyfunc)) {
1014                         pyargs = PyTuple_New(1);
1015
1016                         if (get_obj(&pyarg, jd_func, jd) != -1) {
1017                         }
1018
1019                         /* */
1020
1021                         PyTuple_SetItem(pyargs, 0, pyarg);
1022
1023                         pyret = PyObject_CallObject(pyfunc, pyargs);
1024                         if (pyret == NULL) {
1025                 PyErr_Print();
1026                         } else {
1027                                 success = 1;
1028                         }
1029                 } else {
1030                         if (PyErr_Occurred())
1031                                 PyErr_Print();
1032                 }
1033         } else {
1034                 PyErr_Print();
1035         }
1036
1037         Py_XDECREF(pymodname);
1038         Py_XDECREF(pymod);
1039         Py_XDECREF(pyargs);
1040         Py_XDECREF(pyret);
1041
1042         return (success == 1 ? 1 : 0);
1043 }
1044
1045 /*
1046  * These are local overrides for various environment variables in Emacs.
1047  * Please do not remove this and leave it at the end of the file, where
1048  * Emacs will automagically detect them.
1049  * ---------------------------------------------------------------------
1050  * Local variables:
1051  * mode: c
1052  * indent-tabs-mode: t
1053  * c-basic-offset: 4
1054  * tab-width: 4
1055  * End:
1056  * vim:noexpandtab:sw=4:ts=4:
1057  */