1 /* src/vm/jit/python.c - Python pass
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
8 This file is part of CACAO.
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.
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.
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
25 Note: this code is currently alpha and needs to be documented.
27 This code wraps the jitdata structure into a python object and
28 makes it possible to implement a compiler pass as python function.
30 The wrapping of cacao types to python objects is meant to be easy and
33 Cacao structs a wrapped into a python ``wrapper'' object, the state of
37 * A pointer to a class function (see class_func), which implements the
40 Arrays and collection-like data structures are wrapped into a python
41 ``iterator'' object, the state of wich consists of:
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.
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.
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:
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
64 #include "vm/jit/python.h"
81 typedef union class_arg class_arg;
88 typedef enum class_op class_op;
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)
93 struct iterator_state {
109 typedef union iterator_arg iterator_arg;
111 typedef struct iterator_state iterator_state;
122 typedef enum iterator_op iterator_op;
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
128 struct field_map_entry {
133 typedef struct field_map_entry field_map_entry;
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 },
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 },
188 { "local_map", F_LOCAL_MAP },
189 { "local_methodinfo", F_LOCAL_METHODINFO },
190 { "method", F_METHOD },
192 { "name_ex", F_NAME_EX },
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 },
204 { "successors", F_SUCCESSORS },
206 { "unresolved_field", F_UNRESOLVED_FIELD },
211 int field_find(const char *key) {
214 for (it = field_map; it->name; ++it) {
215 if (strcmp(it->name, key) == 0) {
233 typedef struct wrapper wrapper;
235 PyObject *wrapper_getattr(wrapper *w, PyObject *fld) {
239 arg.get.field = field_find(PyString_AsString(fld));
240 if (arg.get.field == -1) {
244 arg.get.result = &result;
246 if (w->func(w->data, GET_FIELD, &arg) == -1) {
253 int wrapper_setattr(wrapper *w, PyObject *fld, PyObject *value) {
256 arg.set.field = field_find(PyString_AsString(fld));
257 if (arg.set.field == -1) {
260 arg.set.value = value;
262 if (w->func(w->data, SET_FIELD, &arg) == -1) {
269 extern PyTypeObject wrapper_type;
271 int wrapper_compare(wrapper *a, wrapper *b) {
272 if (PyObject_TypeCheck(b, &wrapper_type)) {
273 if (a->data < b->data) {
275 } else if (a->data > b->data) {
281 /* If classes differ, compare classes */
282 return PyObject_Compare(a->ob_type, b->ob_type);
286 long wrapper_hash(wrapper *a) {
287 return (long)a->data;
290 PyTypeObject wrapper_type = {
291 PyObject_HEAD_INIT(NULL)
293 "wrapper", /* tp_name */
294 sizeof(wrapper), /* tp_basicsize */
300 wrapper_compare, /* tp_compare */
302 0, /* tp_as_number */
303 0, /* tp_as_sequence */
304 0, /* tp_as_mapping */
305 wrapper_hash, /* tp_hash */
308 wrapper_getattr, /* tp_getattro */
309 wrapper_setattr, /* tp_setattro */
310 0, /* tp_as_buffer */
311 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
315 0, /* tp_richcompare */
316 0, /* tp_weaklistoffset */
324 0, /* tp_descr_get */
325 0, /* tp_descr_set */
326 0, /* tp_dictoffset */
329 PyType_GenericNew, /* tp_new */
335 iterator_state state;
338 typedef struct iterator iterator;
340 PyObject *iterator_iter(struct iterator *it) {
342 return (PyObject *)it;
345 PyObject *iterator_iternext(struct iterator *it) {
349 if (it->func(ITERATOR_END, &it->state, NULL)) {
352 arg.get.result = &ret;
353 it->func(ITERATOR_GET, &it->state, &arg);
354 it->func(ITERATOR_FORWARD, &it->state, NULL);
359 PyObject *iterator_getitem(struct iterator *it, PyObject* item) {
363 if (PyInt_Check(item)) {
364 arg.subscript.index = PyInt_AS_LONG(item);
365 arg.subscript.result = &ret;
368 } else if (it->func(ITERATOR_SUBSCRIPT, &it->state, &arg) != -1) {
378 int iterator_length(struct iterator *it) {
380 if (it->func(ITERATOR_LENGTH, &it->state, &arg) == -1) {
387 PyMappingMethods iterator_mapping = {
393 PyTypeObject iterator_type = {
394 PyObject_HEAD_INIT(NULL)
396 "iterator", /* tp_name */
397 sizeof(iterator), /* tp_basicsize */
405 0, /* tp_as_number */
406 0, /* tp_as_sequence */
407 &iterator_mapping, /* tp_as_mapping */
413 0, /* tp_as_buffer */
414 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
418 0, /* tp_richcompare */
419 0, /* tp_weaklistoffset */
420 iterator_iter, /* tp_iter */
421 iterator_iternext, /* tp_iternext */
427 0, /* tp_descr_get */
428 0, /* tp_descr_set */
429 0, /* tp_dictoffset */
432 PyType_GenericNew, /* tp_new */
439 int set_int(int *p, PyObject *o) {
440 if (PyInt_Check(o)) {
441 *p = PyInt_AsLong(o);
448 int get_int(PyObject **o, int p) {
449 *o = Py_BuildValue("i", p);
453 int get_string(PyObject **o, const char *str) {
454 *o = PyString_FromString(str);
458 int get_obj(PyObject **res, class_func f, void *p) {
460 return get_none(res);
462 PyObject *o = PyObject_CallObject((PyObject *)&wrapper_type, NULL);
463 struct wrapper * w = (struct wrapper *)o;
471 int get_true(PyObject **res) {
477 int get_false(PyObject **res) {
483 int get_none(PyObject **res) {
489 int get_bool(PyObject **res, int cond) {
490 return cond ? get_true(res) : get_false(res);
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;
498 f(ITERATOR_INIT, &it->state, NULL);
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);
514 CLASS_FUNC(basicblock_func);
515 CLASS_FUNC(classinfo_func);
516 CLASS_FUNC(constant_classref_func);
517 CLASS_FUNC(methodinfo_func);
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;
525 return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
529 ITERATOR_FUNC(call_args_iter_func) {
530 instruction *iptr = (instruction *)state->data;
533 state->pos = iptr->sx.s23.s2.args;
535 case ITERATOR_LENGTH:
536 arg->length = instruction_call_site(iptr)->paramcount;
539 return get_int(arg->get.result, *(int *)state->pos);
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;
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]);
552 CLASS_FUNC(fieldinfo_func) {
553 fieldinfo *fi = (fieldinfo *)vp;
557 switch (arg->get.field) {
559 return get_int(arg->get.result, fi->type);
561 return get_int(arg->get.result, fi->offset);
563 return get_string(arg->get.result, fi->name->text);
565 return get_obj(arg->get.result, classinfo_func, fi->class);
572 CLASS_FUNC(unresolved_field_func) {
573 unresolved_field *uf = (unresolved_field *)vp;
576 switch (arg->get.field) {
578 return get_string(arg->get.result, uf->fieldref->name->text);
580 if (IS_FMIREF_RESOLVED(uf->fieldref)) {
581 return get_none(arg->get.result);
583 return get_obj(arg->get.result, constant_classref_func, uf->fieldref->p.classref);
586 return get_string(arg->get.result, uf->fieldref->descriptor->text);
588 if (IS_FMIREF_RESOLVED(uf->fieldref)) {
589 return get_obj(arg->get.result, fieldinfo_func, uf->fieldref->p.field);
591 return get_none(arg->get.result);
593 case F_IS_UNRESOLVED:
594 return get_bool(arg->get.result, !IS_FMIREF_RESOLVED(uf->fieldref));
600 CLASS_FUNC(instruction_func) {
602 instruction *iptr = (instruction *)vp;
606 switch (arg->get.field) {
608 return get_int(arg->get.result, iptr->opc);
610 if (iptr->opc == ICMD_BUILTIN) {
611 return get_int(arg->get.result, iptr->sx.s23.s3.bte->opcode);
613 return get_int(arg->get.result, iptr->opc);
616 return get_string(arg->get.result, icmd_table[iptr->opc].name);
618 if (iptr->opc == ICMD_BUILTIN) {
619 return get_string(arg->get.result, icmd_table[iptr->sx.s23.s3.bte->opcode].name);
621 return get_string(arg->get.result, icmd_table[iptr->opc].name);
624 return get_int(arg->get.result, iptr->s1.varindex);
626 return get_int(arg->get.result, iptr->sx.s23.s2.varindex);
628 return get_int(arg->get.result, iptr->sx.s23.s3.varindex);
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);
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);
640 return get_obj(arg->get.result, classinfo_func, iptr->sx.val.c.cls);
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);
647 return get_obj(arg->get.result, methodinfo_func,
648 iptr->sx.s23.s3.fmiref->p.method);
651 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
652 return get_int(arg->get.result,
653 iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type);
655 return get_int(arg->get.result,
656 iptr->sx.s23.s3.fmiref->p.field->type);
659 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
660 return get_none(arg->get.result);
662 return get_obj(arg->get.result, fieldinfo_func, iptr->sx.s23.s3.fmiref->p.field);
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);
669 return get_none(arg->get.result);
673 return get_int(arg->get.result, iptr->line);
680 ITERATOR_FUNC(predecessors_iter_func) {
681 basicblock *bptr = (basicblock *)state->data;
685 state->pos = bptr->predecessors;
688 return get_obj(arg->get.result, basicblock_func, *(basicblock **)state->pos);
691 (state->pos == (bptr->predecessors + bptr->predecessorcount)) ||
692 (bptr->predecessorcount < 0);
693 case ITERATOR_FORWARD:
694 state->pos = ((basicblock **)state->pos) + 1;
701 ITERATOR_FUNC(successors_iter_func) {
702 basicblock *bptr = (basicblock *)state->data;
706 state->pos = bptr->successors;
709 return get_obj(arg->get.result, basicblock_func, *(basicblock **)state->pos);
712 (state->pos == (bptr->successors + bptr->successorcount)) ||
713 (bptr->successorcount < 0);
714 case ITERATOR_FORWARD:
715 state->pos = ((basicblock **)state->pos) + 1;
722 ITERATOR_FUNC(instruction_iter_func) {
723 basicblock *bptr = (basicblock *)state->data;
727 state->pos = bptr->iinstr;
730 return get_obj(arg->get.result, instruction_func, state->pos);
731 case ITERATOR_FORWARD:
732 state->pos = ((instruction *)state->pos) + 1;
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;
746 CLASS_FUNC(basicblock_func) {
747 basicblock *bptr = (basicblock *)vp;
751 switch (arg->get.field) {
753 return get_iter(arg->get.result, instruction_iter_func, bptr);
755 return get_int(arg->get.result, bptr->nr);
757 return get_iter(arg->get.result, predecessors_iter_func, bptr);
759 return get_iter(arg->get.result, successors_iter_func, bptr);
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);
770 ITERATOR_FUNC(basicblocks_iter_func) {
771 jitdata *jd = (jitdata *)state->data;
775 state->pos = jd->basicblocks;
778 return get_obj(arg->get.result, basicblock_func, state->pos);
779 case ITERATOR_FORWARD:
780 state->pos = ((basicblock *)(state->pos))->next;
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);
795 CLASS_FUNC(classinfo_func) {
796 classinfo *c = (classinfo *)vp;
799 switch (arg->get.field) {
801 return get_string(arg->get.result, c->name->text);
807 CLASS_FUNC(constant_classref_func) {
808 constant_classref *cr = (constant_classref *)vp;
811 switch (arg->get.field) {
813 return get_string(arg->get.result, cr->name->text);
819 ITERATOR_FUNC(param_types_iter_func) {
820 methodinfo *m = (methodinfo *)state->data;
824 state->pos = m->parseddesc->paramtypes;
827 return state->pos == (m->parseddesc->paramtypes + m->parseddesc->paramcount);
828 case ITERATOR_FORWARD:
829 state->pos = ((typedesc *)state->pos) + 1;
832 return get_int(arg->get.result, ((typedesc *)state->pos)->type);
833 case ITERATOR_LENGTH:
834 arg->length = m->parseddesc->paramcount;
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);
844 CLASS_FUNC(methodinfo_func) {
845 methodinfo *m = (methodinfo *)vp;
848 switch (arg->get.field) {
850 return get_string(arg->get.result, m->name->text);
852 return get_obj(arg->get.result, classinfo_func, m->class);
854 return get_iter(arg->get.result, param_types_iter_func, m);
856 return get_int(arg->get.result, m->parseddesc->returntype.type);
863 CLASS_FUNC(varinfo_func) {
864 varinfo *var = (varinfo *)vp;
867 switch (arg->get.field) {
869 return get_int(arg->get.result, var->type);
875 ITERATOR_FUNC(vars_func) {
876 jitdata *jd = (jitdata *)state->data;
879 state->pos = jd->var;
881 case ITERATOR_FORWARD:
882 state->pos = ((varinfo *)state->pos) + 1;
885 return state->pos == (jd->var + jd->varcount);
887 return get_obj(arg->get.result, varinfo_func, state->pos);
888 case ITERATOR_LENGTH:
889 arg->length = jd->varcount;
891 case ITERATOR_SUBSCRIPT:
892 ITERATOR_SUBSCRIPT_CHECK(jd->varcount);
893 return get_obj(arg->subscript.result, varinfo_func, jd->var + arg->subscript.index);
898 ITERATOR_FUNC(local_map_2_iter_func) {
899 int *arr = (int *)state->data;
901 case ITERATOR_SUBSCRIPT:
902 ITERATOR_SUBSCRIPT_CHECK(5);
903 return get_int(arg->subscript.result, arr[arg->subscript.index]);
904 case ITERATOR_LENGTH:
911 ITERATOR_FUNC(local_map_iter_func) {
912 jitdata *jd = (jitdata *)state->data;
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));
922 CLASS_FUNC(jd_func) {
923 jitdata *jd = (jitdata *)vp;
927 switch (arg->get.field) {
929 return get_iter(arg->get.result, basicblocks_iter_func, jd);
931 return get_obj(arg->get.result, methodinfo_func, jd->m);
933 return get_iter(arg->get.result, vars_func, jd);
935 return get_iter(arg->get.result, local_map_iter_func, jd);
942 void constants(PyObject *m) {
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, ' ');
955 add_const(m, buf, i);
958 # define c(x) add_const(m, #x, x)
977 void pythonpass_init() {
981 PyEval_InitThreads();
983 if (PyType_Ready(&wrapper_type) < 0) return;
984 if (PyType_Ready(&iterator_type) < 0) return;
986 m = Py_InitModule3("cacao", NULL, NULL);
993 void pythonpass_cleanup() {
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;
1007 pymodname = PyString_FromString(module);
1008 pymod = PyImport_Import(pymodname);
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);
1016 if (get_obj(&pyarg, jd_func, jd) != -1) {
1021 PyTuple_SetItem(pyargs, 0, pyarg);
1023 pyret = PyObject_CallObject(pyfunc, pyargs);
1024 if (pyret == NULL) {
1030 if (PyErr_Occurred())
1037 Py_XDECREF(pymodname);
1042 return (success == 1 ? 1 : 0);
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 * ---------------------------------------------------------------------
1052 * indent-tabs-mode: t
1056 * vim:noexpandtab:sw=4:ts=4: