1 /* src/vm/jit/python.c - Python pass
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Note: this code is currently alpha and needs to be documented.
25 This code wraps the jitdata structure into a python object and
26 makes it possible to implement a compiler pass as python function.
28 The wrapping of cacao types to python objects is meant to be easy and
31 Cacao structs a wrapped into a python ``wrapper'' object, the state of
35 * A pointer to a class function (see class_func), which implements the
38 Arrays and collection-like data structures are wrapped into a python
39 ``iterator'' object, the state of wich consists of:
42 * Another void pointer that is the cursor.
43 * A pointer to a iterator function (see iterator_func) which implements
44 the iterator's behaviour.
46 Because in python field names are identified as strings, to avoid a lot
47 of string comparisons, we translate the field as early as possible into
48 an integer constant. This is achieved using the field_map array.
50 We could have used a wrapper generator like swig, but we don't want to
51 wrap the rather low level C api to python 1:1. When wrapping stuff, try
52 to do it rather high level and in a pythonic way. Examples:
54 * Bad: instruction.flags and cacao.FLAG_UNRESOLVED == 0
55 * Good: instruction.is_unresolved
56 * Bad: for i in range(0, bb.icount): instr = bb.instructions[i]
57 * Good: for instr in bb.instructions
59 Adding instructions or variables is currently problematic, because it
60 requires to resize fixed sized arrays. Reallocating an array means that
61 all elements are possibly moved, their addresses are changed and the
62 associated python object become invalid. Further, usually there is the
63 need to add several instructions, which possibly results in several
64 reallocations of the array. A good solution would be:
66 * Copy-on-write the array (ex. bptr->instructions) into a python list,
67 and put that list into the dictionnary of the parent object.
68 * When the python parent object is destroyed, recreate the array from the
70 * From python, bptr.instructions will return either the wrapped array, or
71 the list from the dictionnary.
76 #include <structmember.h>
78 #include "vm/global.h"
79 #include "vm/jit/python.h"
80 #include "vm/jit/show.hpp"
81 #if defined(ENABLE_THREADS)
82 # include "threads/mutex.hpp"
85 #if defined(ENABLE_THREADS)
86 static Mutex *python_global_mutex;
93 typedef struct root_state root_state;
97 PyObject *object_cache;
100 typedef struct class_state class_state;
132 typedef union class_arg class_arg;
142 typedef enum class_op class_op;
144 typedef int(*class_func)(class_op, class_state *, class_arg *);
145 #define CLASS_FUNC(name) int name(class_op op, class_state *state, class_arg *arg)
146 #define CLASS_FUNC_CALL(name) name(op, state, arg)
148 struct iterator_state {
169 typedef union iterator_arg iterator_arg;
171 typedef struct iterator_state iterator_state;
183 typedef enum iterator_op iterator_op;
185 typedef int(*iterator_func)(iterator_op op, iterator_state *state, iterator_arg *arg);
186 #define ITERATOR_FUNC(name) int name (iterator_op op, iterator_state *state, iterator_arg *arg)
187 #define ITERATOR_SUBSCRIPT_CHECK(end) if (arg->subscript.index >= (end)) return -1
188 #define ITERATOR_SETITEM_CHECK(end) if (arg->setitem.index >= (end)) return -1
190 typedef struct method_state method_state;
192 struct method_state {
197 struct field_map_entry {
202 typedef struct field_map_entry field_map_entry;
215 F_DOMINANCE_FRONTIER,
268 /* Keep it soreted alphabetically, so we can support binary search in future. */
269 struct field_map_entry field_map[] = {
270 { "basic_blocks", F_BASIC_BLOCKS },
271 { "call_return_type", F_CALL_RETURN_TYPE },
272 { "call_args", F_CALL_ARGS },
273 { "classref", F_CLASSREF },
274 { "control_flow", F_CONTROL_FLOW },
275 { "control_flow_ex", F_CONTROL_FLOW_EX },
276 { "data_flow", F_DATA_FLOW },
277 { "data_flow_ex", F_DATA_FLOW_EX },
278 { "descriptor", F_DESCRIPTOR },
279 { "dom_successors", F_DOM_SUCCESSORS },
280 { "dominance_frontier", F_DOMINANCE_FRONTIER },
283 { "exception_handler", F_EXCEPTION_HANDLER },
284 { "exception_table", F_EXCEPTION_TABLE },
285 { "field", F_FIELD },
286 { "field_type", F_FIELD_TYPE },
287 { "handler", F_HANDLER },
288 { "has_call_args", F_HAS_CALL_ARGS },
289 { "has_dst", F_HAS_DST },
291 { "index", F_INDEX },
292 { "instructions", F_INSTRUCTIONS },
293 { "interface_map", F_INTERFACE_MAP },
294 { "in_vars", F_IN_VARS },
295 { "is_class_constant", F_IS_CLASS_CONSTANT },
296 { "is_inout", F_IS_INOUT },
297 { "is_in_memory", F_IS_IN_MEMORY },
298 { "is_local", F_IS_LOCAL },
299 { "is_preallocated", F_IS_PREALLOCATED },
300 { "is_saved", F_IS_SAVED },
301 { "is_temporary", F_IS_TEMPORARY },
302 { "is_unresolved", F_IS_UNRESOLVED },
303 { "klass", F_KLASS },
305 { "local_map", F_LOCAL_MAP },
306 { "local_methodinfo", F_LOCAL_METHODINFO },
307 { "method", F_METHOD },
309 { "name_ex", F_NAME_EX },
311 { "offset", F_OFFSET },
312 { "opcode", F_OPCODE },
313 { "opcode_ex", F_OPCODE_EX },
314 { "out_vars", F_OUT_VARS },
315 { "params", F_PARAMS },
316 { "param_types", F_PARAM_TYPES },
318 { "pei_ex", F_PEI_EX },
319 { "predecessors", F_PREDECESSORS },
320 { "reached", F_REACHED },
321 { "register_offset", F_REGISTER_OFFSET },
322 { "return_type", F_RETURN_TYPE },
325 { "start", F_START },
326 { "successors", F_SUCCESSORS },
328 { "unresolved_field", F_UNRESOLVED_FIELD },
329 { "unused", F_UNUSED },
334 int field_find(const char *key) {
337 for (it = field_map; it->name; ++it) {
338 if (strcmp(it->name, key) == 0) {
350 typedef struct method method;
358 PyObject *method_call(method *m, PyObject *args, PyObject *kw) {
360 PyObject *result = NULL;
362 arg.method_call.method = m->state.method;
363 arg.method_call.args = args;
364 arg.method_call.result = &result;
366 if (m->func(CLASS_METHOD_CALL, m->state.cstate, &arg) == -1) {
370 if (result == NULL) {
378 PyTypeObject method_type = {
379 PyObject_HEAD_INIT(NULL)
381 "method", /* tp_name */
382 sizeof(method), /* tp_basicsize */
390 0, /* tp_as_number */
391 0, /* tp_as_sequence */
392 0, /* tp_as_mapping */
394 method_call, /* tp_call */
398 0, /* tp_as_buffer */
399 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
403 0, /* tp_richcompare */
404 0, /* tp_weaklistoffset */
412 0, /* tp_descr_get */
413 0, /* tp_descr_set */
414 0, /* tp_dictoffset */
417 PyType_GenericNew, /* tp_new */
427 typedef struct wrapper wrapper;
429 PyObject *wrapper_getattr(wrapper *w, PyObject *fld) {
433 /* First, try generic getattr */
435 result = PyObject_GenericGetAttr(w, fld);
437 if (result != NULL) {
441 /* Exception is set here */
443 arg.get.field = field_find(PyString_AsString(fld));
444 if (arg.get.field == -1) {
448 arg.get.is_method = 0;
449 arg.get.result = &result;
451 if (w->func(CLASS_GET_FIELD, &w->state, &arg) == -1) {
455 if (arg.get.is_method) {
456 result = PyObject_CallObject((PyObject *)&method_type, NULL);
457 method *m = (method *)result;
459 m->state.method = arg.get.field;
460 m->state.cstate = &w->state;
472 int wrapper_setattr(wrapper *w, PyObject *fld, PyObject *value) {
475 arg.set.field = field_find(PyString_AsString(fld));
476 if (arg.set.field == -1) {
479 arg.set.value = value;
481 if (w->func(CLASS_SET_FIELD, &w->state, &arg) == -1) {
489 return PyObject_GenericSetAttr(w, fld, value);
492 extern PyTypeObject wrapper_type;
494 inline void *wrapper_key(wrapper *w) {
498 int wrapper_compare(wrapper *a, wrapper *b) {
500 if (PyObject_TypeCheck(b, &wrapper_type)) {
501 keya = wrapper_key(a);
502 keyb = wrapper_key(b);
505 } else if (keya > keyb) {
511 /* If classes differ, compare classes */
512 return PyObject_Compare(a->ob_type, b->ob_type);
516 long wrapper_hash(wrapper *a) {
517 return (long)wrapper_key(a);
520 PyObject *wrapper_call(wrapper *w, PyObject *args, PyObject *kw) {
524 arg.call.args = args;
525 arg.call.result = &result;
527 if (w->func(CLASS_CALL, &w->state, &arg) == -1) {
534 PyObject *wrapper_str(wrapper *w) {
537 arg.str.result = &result;
538 if (w->func(CLASS_STR, &w->state, &arg) == -1) {
539 return PyString_FromFormat("Wrapper(0x%p)", w->state.vp);
545 PyTypeObject wrapper_type = {
546 PyObject_HEAD_INIT(NULL)
548 "wrapper", /* tp_name */
549 sizeof(wrapper), /* tp_basicsize */
555 wrapper_compare, /* tp_compare */
556 wrapper_str, /* tp_repr */
557 0, /* tp_as_number */
558 0, /* tp_as_sequence */
559 0, /* tp_as_mapping */
560 wrapper_hash, /* tp_hash */
561 wrapper_call, /* tp_call */
562 wrapper_str, /* tp_str */
563 wrapper_getattr, /* tp_getattro */
564 wrapper_setattr, /* tp_setattro */
565 0, /* tp_as_buffer */
566 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
570 0, /* tp_richcompare */
571 0, /* tp_weaklistoffset */
579 0, /* tp_descr_get */
580 0, /* tp_descr_set */
581 offsetof(wrapper, dict), /* tp_dictoffset */
584 PyType_GenericNew, /* tp_new */
590 iterator_state state;
593 typedef struct iterator iterator;
595 PyObject *iterator_iter(struct iterator *it) {
597 return (PyObject *)it;
600 PyObject *iterator_iternext(struct iterator *it) {
604 if (it->func(ITERATOR_END, &it->state, NULL)) {
607 arg.get.result = &ret;
608 it->func(ITERATOR_GET, &it->state, &arg);
609 it->func(ITERATOR_FORWARD, &it->state, NULL);
614 PyObject *iterator_getitem(struct iterator *it, PyObject* item) {
618 if (PyInt_Check(item)) {
619 arg.subscript.index = PyInt_AS_LONG(item);
620 arg.subscript.result = &ret;
623 } else if (it->func(ITERATOR_SUBSCRIPT, &it->state, &arg) != -1) {
633 int iterator_setitem(struct iterator *it, PyObject *item, PyObject *value) {
635 if (PyInt_Check(item)) {
636 arg.setitem.index = PyInt_AS_LONG(item);
637 arg.setitem.value = value;
638 if (it->func(ITERATOR_SETITEM, &it->state, &arg) != -1) {
648 int iterator_length(struct iterator *it) {
650 if (it->func(ITERATOR_LENGTH, &it->state, &arg) == -1) {
657 PyMappingMethods iterator_mapping = {
663 PyTypeObject iterator_type = {
664 PyObject_HEAD_INIT(NULL)
666 "iterator", /* tp_name */
667 sizeof(iterator), /* tp_basicsize */
675 0, /* tp_as_number */
676 0, /* tp_as_sequence */
677 &iterator_mapping, /* tp_as_mapping */
683 0, /* tp_as_buffer */
684 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
688 0, /* tp_richcompare */
689 0, /* tp_weaklistoffset */
690 iterator_iter, /* tp_iter */
691 iterator_iternext, /* tp_iternext */
697 0, /* tp_descr_get */
698 0, /* tp_descr_set */
699 0, /* tp_dictoffset */
702 PyType_GenericNew, /* tp_new */
709 int set_s4(s4 *p, PyObject *o) {
710 if (PyInt_Check(o)) {
711 *p = PyInt_AsLong(o);
718 int set_s4_flag(s4 *p, s4 flag, PyObject *o) {
722 } else if (o == Py_False) {
730 int get_int(PyObject **o, int p) {
731 *o = PyInt_FromLong(p);
735 int get_string(PyObject **o, const char *str) {
736 *o = PyString_FromString(str);
740 int get_obj(PyObject **res, class_func f, root_state *root, void *p) {
742 return get_none(res);
744 PyObject *key = PyInt_FromLong((long)p);
745 PyObject *o = PyDict_GetItem(root->object_cache, key);
747 o = PyObject_CallObject((PyObject *)&wrapper_type, NULL);
748 struct wrapper * w = (struct wrapper *)o;
750 w->state.root = root;
752 PyDict_SetItem(root->object_cache, key, o);
761 int get_true(PyObject **res) {
767 int get_false(PyObject **res) {
773 int get_none(PyObject **res) {
779 int get_bool(PyObject **res, int cond) {
780 return cond ? get_true(res) : get_false(res);
783 int get_iter(PyObject **res, iterator_func f, root_state *root, void *p) {
784 PyObject *o = PyObject_CallObject((PyObject *)&iterator_type, NULL);
785 struct iterator * it = (struct iterator *)o;
787 it->state.root = root;
789 f(ITERATOR_INIT, &it->state, NULL);
794 int add_const(PyObject *module, const char *name, int value) {
795 PyObject *pyvalue = PyInt_FromLong(value);
796 if (pyvalue != NULL) {
797 PyModule_AddObject(module, name, pyvalue);
801 void *get_vp(PyObject *o, class_func func) {
802 if (o->ob_type == &wrapper_type) {
803 if (((wrapper *)o)->func == func) {
804 return ((wrapper *)o)->state.vp;
814 CLASS_FUNC(basicblock_func);
815 CLASS_FUNC(classinfo_func);
816 CLASS_FUNC(constant_classref_func);
817 CLASS_FUNC(methodinfo_func);
818 CLASS_FUNC(varinfo_func);
820 int get_varinfo(PyObject **res, root_state *root, s4 index) {
821 return get_obj(res, varinfo_func, root, root->jd->var + index);
824 static inline int instruction_opcode_ex(instruction *iptr) {
825 if (iptr->opc == ICMD_BUILTIN) {
826 return iptr->sx.s23.s3.bte->opcode;
832 ITERATOR_FUNC(call_args_iter_func) {
833 instruction *iptr = (instruction *)state->data;
836 state->pos = iptr->sx.s23.s2.args;
838 case ITERATOR_LENGTH:
839 arg->length = iptr->s1.argcount;
842 /* return get_int(arg->get.result, *(int *)state->pos);*/
843 return get_varinfo(arg->get.result, state->root, *(int *)state->pos);
845 return state->pos == iptr->sx.s23.s2.args + iptr->s1.argcount;
846 case ITERATOR_FORWARD:
847 state->pos = ((int *)state->pos) + 1;
849 case ITERATOR_SUBSCRIPT:
850 ITERATOR_SUBSCRIPT_CHECK(iptr->s1.argcount);
851 return get_int(arg->subscript.result, iptr->sx.s23.s2.args[arg->subscript.index]);
852 case ITERATOR_SETITEM:
853 ITERATOR_SETITEM_CHECK(iptr->s1.argcount);
854 return set_s4(iptr->sx.s23.s2.args + arg->setitem.index, arg->setitem.value);
859 CLASS_FUNC(fieldinfo_func) {
860 fieldinfo *fi = (fieldinfo *)state->vp;
863 case CLASS_GET_FIELD:
864 switch (arg->get.field) {
866 return get_int(arg->get.result, fi->type);
868 return get_int(arg->get.result, fi->offset);
870 return get_string(arg->get.result, fi->name->text);
872 return get_obj(arg->get.result, classinfo_func, state->root, fi->clazz);
879 CLASS_FUNC(unresolved_field_func) {
880 unresolved_field *uf = (unresolved_field *)state->vp;
882 case CLASS_GET_FIELD:
883 switch (arg->get.field) {
885 return get_string(arg->get.result, uf->fieldref->name->text);
887 if (IS_FMIREF_RESOLVED(uf->fieldref)) {
888 return get_none(arg->get.result);
890 return get_obj(arg->get.result, constant_classref_func, state->root, uf->fieldref->p.classref);
893 return get_string(arg->get.result, uf->fieldref->descriptor->text);
895 if (IS_FMIREF_RESOLVED(uf->fieldref)) {
896 return get_obj(arg->get.result, fieldinfo_func, state->root, uf->fieldref->p.field);
898 return get_none(arg->get.result);
900 case F_IS_UNRESOLVED:
901 return get_bool(arg->get.result, !IS_FMIREF_RESOLVED(uf->fieldref));
907 static inline int instruction_num_s(instruction *iptr) {
908 switch (icmd_table[iptr->opc].dataflow) {
925 static inline s4 *instruction_get_s(instruction *iptr, int s) {
928 return &(iptr->s1.varindex);
930 return &(iptr->sx.s23.s2.varindex);
932 return &(iptr->sx.s23.s3.varindex);
936 ITERATOR_FUNC(s_iter_func) {
937 instruction *iptr = (instruction *)state->data;
938 uintptr_t pos = (uintptr_t)state->pos;
942 state->pos = (void *)0;
944 case ITERATOR_LENGTH:
945 arg->length = instruction_num_s(iptr);
948 return get_varinfo(arg->get.result, state->root,
949 *instruction_get_s(iptr, pos));
951 return pos == instruction_num_s(iptr);
952 case ITERATOR_FORWARD:
953 state->pos = (void *)(pos + 1);
955 case ITERATOR_SUBSCRIPT:
956 ITERATOR_SUBSCRIPT_CHECK(3);
957 return get_varinfo(arg->subscript.result, state->root,
958 *instruction_get_s(iptr, arg->subscript.index));
959 case ITERATOR_SETITEM:
960 ITERATOR_SETITEM_CHECK(3);
961 return set_s4(instruction_get_s(iptr, arg->setitem.index),
967 CLASS_FUNC(instruction_func) {
969 instruction *iptr = (instruction *)state->vp;
972 case CLASS_GET_FIELD:
973 switch (arg->get.field) {
975 return get_int(arg->get.result, iptr->opc);
977 return get_int(arg->get.result, instruction_opcode_ex(iptr));
979 return get_string(arg->get.result, icmd_table[iptr->opc].name);
981 return get_string(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].name);
983 return get_iter(arg->get.result, s_iter_func, state->root, iptr);
985 return get_varinfo(arg->get.result, state->root,
989 (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
990 (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
994 instruction_call_site(iptr)->returntype.type != TYPE_VOID
997 return get_bool(arg->get.result, icmd_table[iptr->opc].dataflow >= DF_DST_BASE);
998 case F_CALL_RETURN_TYPE:
999 return get_int(arg->get.result, instruction_call_site(iptr)->returntype.type);
1001 return get_iter(arg->get.result, call_args_iter_func, state->root, iptr);
1002 case F_HAS_CALL_ARGS:
1003 return get_bool(arg->get.result,
1004 icmd_table[iptr->opc].dataflow == DF_INVOKE ||
1005 icmd_table[iptr->opc].dataflow == DF_BUILTIN ||
1006 icmd_table[iptr->opc].dataflow == DF_N_TO_1
1008 case F_IS_UNRESOLVED:
1009 return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_UNRESOLVED);
1010 case F_IS_CLASS_CONSTANT:
1011 return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_CLASS);
1013 return get_obj(arg->get.result, classinfo_func, state->root, iptr->sx.val.c.cls);
1015 return get_obj(arg->get.result, constant_classref_func, state->root, iptr->sx.val.c.ref);
1016 case F_LOCAL_METHODINFO:
1017 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1018 return get_none(arg->get.result);
1020 return get_obj(arg->get.result, methodinfo_func,
1021 state->root, iptr->sx.s23.s3.fmiref->p.method);
1024 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1025 return get_int(arg->get.result,
1026 iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type);
1028 return get_int(arg->get.result,
1029 iptr->sx.s23.s3.fmiref->p.field->type);
1032 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1033 return get_none(arg->get.result);
1035 return get_obj(arg->get.result, fieldinfo_func, state->root, iptr->sx.s23.s3.fmiref->p.field);
1038 case F_UNRESOLVED_FIELD:
1039 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1040 return get_obj(arg->get.result, unresolved_field_func, state->root, iptr->sx.s23.s3.uf);
1042 return get_none(arg->get.result);
1046 return get_int(arg->get.result, iptr->line);
1048 return get_bool(arg->get.result, icmd_table[iptr->opc].flags & ICMDTABLE_PEI);
1050 return get_bool(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].flags & ICMDTABLE_PEI);
1052 return get_int(arg->get.result, icmd_table[iptr->opc].dataflow);
1053 case F_DATA_FLOW_EX:
1054 return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].dataflow);
1055 case F_CONTROL_FLOW:
1056 return get_int(arg->get.result, icmd_table[iptr->opc].controlflow);
1057 case F_CONTROL_FLOW_EX:
1058 return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].controlflow);
1060 arg->get.is_method = 1;
1063 case CLASS_SET_FIELD:
1064 switch (arg->set.field) {
1066 return set_s4(&(iptr->dst.varindex), arg->set.value);
1068 return set_s4(&(iptr->opc), arg->set.value);
1070 case CLASS_METHOD_CALL:
1071 switch (arg->method_call.method) {
1073 show_icmd(state->root->jd, iptr, 1, SHOW_CFG);
1081 ITERATOR_FUNC(predecessors_iter_func) {
1082 basicblock *bptr = (basicblock *)state->data;
1086 state->pos = bptr->predecessors;
1089 return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
1090 case ITERATOR_SUBSCRIPT:
1091 ITERATOR_SUBSCRIPT_CHECK(bptr->predecessorcount);
1092 return get_obj(arg->subscript.result, basicblock_func, state->root,
1093 bptr->predecessors[arg->subscript.index]);
1096 (state->pos == (bptr->predecessors + bptr->predecessorcount)) ||
1097 (bptr->predecessorcount < 0);
1098 case ITERATOR_FORWARD:
1099 state->pos = ((basicblock **)state->pos) + 1;
1101 case ITERATOR_LENGTH:
1102 arg->length = bptr->predecessorcount;
1109 ITERATOR_FUNC(successors_iter_func) {
1110 basicblock *bptr = (basicblock *)state->data;
1114 state->pos = bptr->successors;
1117 return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
1118 case ITERATOR_SUBSCRIPT:
1119 ITERATOR_SUBSCRIPT_CHECK(bptr->successorcount);
1120 return get_obj(arg->subscript.result, basicblock_func, state->root,
1121 bptr->successors[arg->subscript.index]);
1124 (state->pos == (bptr->successors + bptr->successorcount)) ||
1125 (bptr->successorcount < 0);
1126 case ITERATOR_FORWARD:
1127 state->pos = ((basicblock **)state->pos) + 1;
1129 case ITERATOR_LENGTH:
1130 arg->length = bptr->successorcount;
1137 ITERATOR_FUNC(dom_successors_iter_func) {
1138 basicblock *bptr = (basicblock *)state->data;
1142 state->pos = bptr->domsuccessors;
1145 return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
1147 return (state->pos == (bptr->domsuccessors + bptr->domsuccessorcount));
1148 case ITERATOR_FORWARD:
1149 state->pos = ((basicblock **)state->pos) + 1;
1151 case ITERATOR_LENGTH:
1152 arg->length = bptr->domsuccessorcount;
1159 ITERATOR_FUNC(dominance_frontier_iter_func) {
1160 basicblock *bptr = (basicblock *)state->data;
1164 state->pos = bptr->domfrontier;
1167 return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
1169 return (state->pos == (bptr->domfrontier + bptr->domfrontiercount));
1170 case ITERATOR_FORWARD:
1171 state->pos = ((basicblock **)state->pos) + 1;
1178 ITERATOR_FUNC(instruction_iter_func) {
1179 basicblock *bptr = (basicblock *)state->data;
1183 state->pos = bptr->iinstr;
1186 return get_obj(arg->get.result, instruction_func, state->root, state->pos);
1187 case ITERATOR_FORWARD:
1188 state->pos = ((instruction *)state->pos) + 1;
1191 return state->pos == (bptr->iinstr + bptr->icount);
1192 case ITERATOR_SUBSCRIPT:
1193 ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
1194 return get_obj(arg->subscript.result, instruction_func, state->root, bptr->iinstr + arg->subscript.index);
1195 case ITERATOR_LENGTH:
1196 arg->length = bptr->icount;
1202 ITERATOR_FUNC(in_vars_iter_func) {
1203 basicblock *bptr = (basicblock *)state->data;
1206 state->pos = bptr->invars;
1209 return get_varinfo(arg->get.result, state->root, *(s4 *)(state->pos));
1210 case ITERATOR_FORWARD:
1211 state->pos = ((s4 *)state->pos) + 1;
1214 return state->pos == (bptr->invars + bptr->indepth);
1215 case ITERATOR_SUBSCRIPT:
1216 ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
1217 return get_varinfo(arg->subscript.result, state->root, bptr->invars[arg->subscript.index]);
1218 case ITERATOR_LENGTH:
1219 arg->length = bptr->indepth;
1224 ITERATOR_FUNC(out_vars_iter_func) {
1225 basicblock *bptr = (basicblock *)state->data;
1228 state->pos = bptr->outvars;
1231 return get_varinfo(arg->get.result, state->root, *(s4 *)(state->pos));
1232 case ITERATOR_FORWARD:
1233 state->pos = ((s4 *)state->pos) + 1;
1236 return state->pos == (bptr->outvars + bptr->outdepth);
1237 case ITERATOR_SUBSCRIPT:
1238 ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
1239 return get_varinfo(arg->subscript.result, state->root, bptr->outvars[arg->subscript.index]);
1240 case ITERATOR_LENGTH:
1241 arg->length = bptr->outdepth;
1246 CLASS_FUNC(basicblock_func) {
1247 basicblock *bptr = (basicblock *)state->vp;
1250 case CLASS_GET_FIELD:
1251 switch (arg->get.field) {
1252 case F_INSTRUCTIONS:
1253 return get_iter(arg->get.result, instruction_iter_func, state->root, bptr);
1255 return get_int(arg->get.result, bptr->nr);
1256 case F_PREDECESSORS:
1257 return get_iter(arg->get.result, predecessors_iter_func, state->root, bptr);
1259 return get_iter(arg->get.result, successors_iter_func, state->root, bptr);
1261 return get_bool(arg->get.result, bptr->flags >= BBREACHED);
1262 case F_EXCEPTION_HANDLER:
1263 return get_bool(arg->get.result, bptr->type == BBTYPE_EXH);
1265 return get_obj(arg->get.result, basicblock_func, state->root, bptr->idom);
1266 case F_DOM_SUCCESSORS:
1267 return get_iter(arg->get.result, dom_successors_iter_func, state->root, bptr);
1268 case F_DOMINANCE_FRONTIER:
1269 return get_iter(arg->get.result, dominance_frontier_iter_func, state->root, bptr);
1271 return get_iter(arg->get.result, in_vars_iter_func, state->root, bptr);
1273 return get_iter(arg->get.result, in_vars_iter_func, state->root, bptr);
1275 arg->get.is_method = 1;
1279 *arg->str.result = PyString_FromFormat("BB_%d", bptr->nr);
1281 case CLASS_METHOD_CALL:
1282 switch (arg->method_call.method) {
1284 show_basicblock(state->root->jd, bptr, SHOW_CFG);
1292 ITERATOR_FUNC(basicblocks_iter_func) {
1293 jitdata *jd = (jitdata *)state->data;
1298 state->pos = jd->basicblocks;
1301 return get_obj(arg->get.result, basicblock_func, state->root, state->pos);
1302 case ITERATOR_FORWARD:
1303 state->pos = ((basicblock *)(state->pos))->next;
1306 return (state->pos == NULL);
1307 case ITERATOR_SUBSCRIPT:
1308 for (bb = jd->basicblocks; bb != NULL; bb = bb->next) {
1309 if (bb->nr == arg->subscript.index) {
1310 return get_obj(arg->subscript.result, basicblock_func, state->root, bb);
1319 CLASS_FUNC(classinfo_func) {
1320 classinfo *c = (classinfo *)state->vp;
1322 case CLASS_GET_FIELD:
1323 switch (arg->get.field) {
1325 return get_string(arg->get.result, c->name->text);
1331 CLASS_FUNC(constant_classref_func) {
1332 constant_classref *cr = (constant_classref *)state->vp;
1334 case CLASS_GET_FIELD:
1335 switch (arg->get.field) {
1337 return get_string(arg->get.result, cr->name->text);
1343 ITERATOR_FUNC(param_types_iter_func) {
1344 methodinfo *m = (methodinfo *)state->data;
1348 state->pos = m->parseddesc->paramtypes;
1351 return state->pos == (m->parseddesc->paramtypes + m->parseddesc->paramcount);
1352 case ITERATOR_FORWARD:
1353 state->pos = ((typedesc *)state->pos) + 1;
1356 return get_int(arg->get.result, ((typedesc *)state->pos)->type);
1357 case ITERATOR_LENGTH:
1358 arg->length = m->parseddesc->paramcount;
1360 case ITERATOR_SUBSCRIPT:
1361 ITERATOR_SUBSCRIPT_CHECK(m->parseddesc->paramcount);
1362 return get_int(arg->subscript.result, m->parseddesc->paramtypes[arg->subscript.index].type);
1368 ITERATOR_FUNC(params_iter_func) {
1370 methodinfo *m = (methodinfo *)state->data;
1372 uint16_t p = (uintptr_t)(state->pos) & 0xFFFF;
1374 uint16_t l = ((uintptr_t)(state->pos) >> 16) & 0xFFFF;
1380 state->pos = (void *)0;
1383 return p == m->parseddesc->paramcount;
1384 case ITERATOR_FORWARD:
1385 l += (IS_2_WORD_TYPE(m->parseddesc->paramtypes[p].type) ? 2 : 1);
1387 state->pos = (void *)(uintptr_t)((l << 16) | p);
1390 varnum = state->root->jd->local_map[(5 * l) + m->parseddesc->paramtypes[p].type];
1391 return get_varinfo(arg->get.result, state->root, varnum);
1397 CLASS_FUNC(methodinfo_func) {
1398 methodinfo *m = (methodinfo *)state->vp;
1400 case CLASS_GET_FIELD:
1401 switch (arg->get.field) {
1403 return get_string(arg->get.result, m->name->text);
1405 return get_obj(arg->get.result, classinfo_func, state->root, m->clazz);
1407 return get_iter(arg->get.result, param_types_iter_func, state->root, m);
1409 if (m == state->root->jd->m) {
1410 return get_iter(arg->get.result, params_iter_func, state->root, m);
1412 return get_none(arg->get.result);
1415 return get_int(arg->get.result, m->parseddesc->returntype.type);
1417 if (m == state->root->jd->m) {
1418 arg->get.is_method = 1;
1422 case CLASS_METHOD_CALL:
1423 switch (arg->method_call.method) {
1425 show_method(state->root->jd, SHOW_CFG);
1432 static inline PyObject *varinfo_str(jitdata *jd, int index, varinfo *v) {
1437 case TYPE_INT: type = 'i'; break;
1438 case TYPE_LNG: type = 'l'; break;
1439 case TYPE_FLT: type = 'f'; break;
1440 case TYPE_DBL: type = 'd'; break;
1441 case TYPE_ADR: type = 'a'; break;
1442 case TYPE_RET: type = 'r'; break;
1443 default: type = '?';
1446 if (index < jd->localcount) {
1450 if (v->flags & PREALLOC) {
1452 if (v->flags & INOUT) {
1453 /* PREALLOC is used to avoid allocation of TYPE_RET */
1454 if (v->type == TYPE_RET)
1458 else if (v->flags & INOUT)
1465 return PyString_FromString("UNUSED");
1467 return PyString_FromFormat("%c%c%d", kind, type, index);
1472 CLASS_FUNC(varinfo_func) {
1473 jitdata *jd = state->root->jd;
1474 varinfo *var = (varinfo *)state->vp;
1475 int index = var - jd->var;
1478 case CLASS_GET_FIELD:
1479 switch (arg->get.field) {
1481 return get_int(arg->get.result, var->type);
1483 return get_bool(arg->get.result, index < jd->localcount);
1484 case F_IS_PREALLOCATED:
1487 (index >= jd->localcount) && (var->flags & PREALLOC)
1492 (index >= jd->localcount) && !(var->flags & PREALLOC) && (var->flags & INOUT)
1494 case F_IS_TEMPORARY:
1497 (index >= jd->localcount) && !(var->flags & PREALLOC) && !(var->flags & INOUT)
1500 return get_bool(arg->get.result, var->flags & SAVEDVAR);
1502 return get_int(arg->get.result, index);
1504 return get_bool(arg->get.result, index == UNUSED);
1505 case F_REGISTER_OFFSET:
1506 return get_int(arg->get.result, var->vv.regoff);
1507 case F_IS_IN_MEMORY:
1508 return get_bool(arg->get.result, var->flags & INMEMORY);
1510 case CLASS_SET_FIELD:
1511 switch (arg->set.field) {
1513 return set_s4(&(var->type), arg->set.value);
1515 if (PyBool_Check(arg->set.value)) {
1516 if (arg->set.value == Py_True) {
1517 if (jd->localcount < (index + 1)) {
1518 jd->localcount = (index + 1);
1521 if (jd->localcount > (index)) {
1522 jd->localcount = index;
1529 if (PyBool_Check(arg->set.value)) {
1530 if (arg->set.value == Py_True) {
1531 var->flags |= SAVEDVAR;
1533 var->flags &= ~SAVEDVAR;
1538 case F_IS_PREALLOCATED:
1539 if (arg->set.value == Py_True) {
1540 var->flags |= PREALLOC;
1545 if (arg->set.value == Py_True) {
1546 var->flags &= ~PREALLOC;
1547 var->flags |= INOUT;
1551 case F_IS_TEMPORARY:
1552 if (arg->set.value == Py_True) {
1553 var->flags &= ~PREALLOC;
1554 var->flags &= ~INOUT;
1558 case F_REGISTER_OFFSET:
1559 return set_s4(&(var->vv.regoff), arg->set.value);
1560 case F_IS_IN_MEMORY:
1561 return set_s4_flags(&(var->flags), INMEMORY, arg->set.value);
1564 *arg->str.result = varinfo_str(jd, index, var);
1571 int vars_grow(jitdata *jd, unsigned size) {
1573 if (size > 16 * 1024) {
1576 if (size >= jd->varcount) {
1577 newcount = 2 * jd->varcount;
1578 if (size > newcount) {
1581 jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, newcount);
1582 MZERO(jd->var + jd->varcount, varinfo, (newcount - jd->varcount));
1583 jd->varcount = newcount;
1588 ITERATOR_FUNC(vars_iter_func) {
1589 jitdata *jd = (jitdata *)state->data;
1593 state->pos = jd->var;
1595 case ITERATOR_FORWARD:
1596 state->pos = ((varinfo *)state->pos) + 1;
1599 return state->pos == (jd->var + jd->vartop);
1601 return get_obj(arg->get.result, varinfo_func, state->root, state->pos);
1602 case ITERATOR_LENGTH:
1603 arg->length = jd->vartop;
1605 case ITERATOR_SUBSCRIPT:
1606 ITERATOR_SUBSCRIPT_CHECK(jd->vartop);
1607 return get_obj(arg->subscript.result, varinfo_func,
1608 state->root, jd->var + arg->subscript.index);
1609 case ITERATOR_SETITEM:
1610 ITERATOR_SETITEM_CHECK(jd->vartop);
1611 vp = get_vp(arg->setitem.value, varinfo_func);
1613 jd->var[arg->setitem.index] = *(varinfo *)vp;
1621 ITERATOR_FUNC(map_2_iter_func) {
1622 int *arr = (int *)state->data;
1624 case ITERATOR_SUBSCRIPT:
1625 ITERATOR_SUBSCRIPT_CHECK(5);
1626 return get_int(arg->subscript.result, arr[arg->subscript.index]);
1627 case ITERATOR_LENGTH:
1630 case ITERATOR_SETITEM:
1631 ITERATOR_SETITEM_CHECK(5);
1632 return set_s4(arr + arg->subscript.index, arg->setitem.value);
1637 ITERATOR_FUNC(local_map_iter_func) {
1638 jitdata *jd = (jitdata *)state->data;
1640 case ITERATOR_SUBSCRIPT:
1641 ITERATOR_SUBSCRIPT_CHECK(jd->maxlocals);
1642 return get_iter(arg->subscript.result, map_2_iter_func, state->root,
1643 jd->local_map + (5 * arg->subscript.index));
1648 ITERATOR_FUNC(interface_map_iter_func) {
1649 jitdata *jd = (jitdata *)state->data;
1651 case ITERATOR_SUBSCRIPT:
1652 ITERATOR_SUBSCRIPT_CHECK(jd->maxinterfaces);
1653 return get_iter(arg->subscript.result, map_2_iter_func, state->root,
1654 jd->interface_map + (5 * arg->subscript.index));
1659 ITERATOR_FUNC(exception_entry_basic_blocks_iter_func) {
1660 exception_entry *ee = (exception_entry *)state->data;
1663 state->pos = ee->start;
1665 case ITERATOR_FORWARD:
1666 state->pos = ((basicblock *)state->pos)->next;
1669 return state->pos == ee->end;
1671 return get_obj(arg->get.result, basicblock_func, state->root, state->pos);
1676 CLASS_FUNC(exception_entry_func) {
1677 exception_entry *ee = (exception_entry *)state->vp;
1679 case CLASS_GET_FIELD:
1680 switch (arg->get.field) {
1682 return get_obj(arg->get.result, basicblock_func, state->root, ee->start);
1684 return get_obj(arg->get.result, basicblock_func, state->root, ee->end);
1686 return get_obj(arg->get.result, basicblock_func, state->root, ee->handler);
1687 case F_BASIC_BLOCKS:
1688 return get_iter(arg->get.result, exception_entry_basic_blocks_iter_func, state->root, ee);
1695 ITERATOR_FUNC(exception_table_iter_func) {
1696 jitdata *jd = (jitdata *)state->data;
1699 state->pos = jd->exceptiontable;
1701 case ITERATOR_FORWARD:
1702 state->pos = ((exception_entry *)state->pos)->down;
1705 return state->pos == NULL;
1707 return get_obj(arg->get.result, exception_entry_func, state->root, state->pos);
1712 CLASS_FUNC(jd_func) {
1713 jitdata *jd = (jitdata *)state->vp;
1716 case CLASS_GET_FIELD:
1717 switch (arg->get.field) {
1718 case F_BASIC_BLOCKS:
1719 return get_iter(arg->get.result, basicblocks_iter_func, state->root, jd);
1721 return get_obj(arg->get.result, methodinfo_func, state->root, jd->m);
1723 return get_iter(arg->get.result, vars_iter_func, state->root, jd);
1725 return get_iter(arg->get.result, local_map_iter_func, state->root, jd);
1726 case F_INTERFACE_MAP:
1727 return get_iter(arg->get.result, interface_map_iter_func, state->root, jd);
1728 case F_EXCEPTION_TABLE:
1729 return get_iter(arg->get.result, exception_table_iter_func, state->root, jd);
1736 void constants(PyObject *m) {
1743 for (i = 0; i < sizeof(icmd_table) / sizeof(icmd_table[0]); ++i) {
1744 snprintf(buf, sizeof(buf), "ICMD_%s", icmd_table[i].name);
1745 pos = strchr(buf, ' ');
1749 add_const(m, buf, i);
1752 # define c(x) add_const(m, #x, x)
1812 void pythonpass_init() {
1816 PyEval_InitThreads();
1818 if (PyType_Ready(&wrapper_type) < 0) return;
1819 if (PyType_Ready(&iterator_type) < 0) return;
1820 if (PyType_Ready(&method_type) < 0) return;
1822 m = Py_InitModule3("cacao", NULL, NULL);
1827 #if defined(ENABLE_THREADS)
1828 python_global_mutex = Mutex_new();
1833 void pythonpass_cleanup() {
1837 int pythonpass_run(jitdata *jd, const char *module, const char *function) {
1838 PyObject *pymodname = NULL;
1839 PyObject *pymod = NULL;
1840 PyObject *pydict = NULL;
1841 PyObject *pyfunc = NULL;
1842 PyObject *pyargs = NULL;
1843 PyObject *pyret = NULL;
1844 PyObject *pyarg = NULL;
1845 PyObject *objcache = NULL;
1849 Mutex_lock(python_global_mutex);
1851 pymodname = PyString_FromString(module);
1852 pymod = PyImport_Import(pymodname);
1855 root.object_cache = objcache = PyDict_New();
1857 if (pymod != NULL) {
1858 pydict = PyModule_GetDict(pymod);
1859 pyfunc = PyDict_GetItemString(pydict, function);
1860 if (pyfunc != NULL && PyCallable_Check(pyfunc)) {
1861 pyargs = PyTuple_New(1);
1863 if (get_obj(&pyarg, jd_func, &root, jd) != -1) {
1868 PyTuple_SetItem(pyargs, 0, pyarg);
1870 pyret = PyObject_CallObject(pyfunc, pyargs);
1871 if (pyret == NULL) {
1877 if (PyErr_Occurred())
1884 Py_XDECREF(pymodname);
1888 Py_XDECREF(objcache);
1890 Mutex_unlock(python_global_mutex);
1892 return (success == 1 ? 1 : 0);
1896 * These are local overrides for various environment variables in Emacs.
1897 * Please do not remove this and leave it at the end of the file, where
1898 * Emacs will automagically detect them.
1899 * ---------------------------------------------------------------------
1902 * indent-tabs-mode: t
1906 * vim:noexpandtab:sw=4:ts=4: