/***************************************************************/ /*** Processor-independent part of code generation ***/ /***************************************************************/ #ifndef _CODEGEN_H #define _CODEGEN_H #include "vcompiler.h" #include #if SIZEOF_LONG == 4 # define SIZE_OF_LONG_BITS 2 #else # error "-----------------------------------------------------" # error "Sorry, non-32-bit platforms are not supported at all." # error "You may try with a Python compiled in 32-bit " # error "compatibility mode. Note that Psyco will probably " # error "never support non-32-bit platforms, as it is no " # error "longer actively developed. Instead, the PyPy group " # error "plans to replace it with a more flexible and easily " # error "retargettable Psyco-for-PyPy during the year 2006. " # error "See http://codespeak.net/pypy/ " # error "-----------------------------------------------------" #endif #if SIZEOF_LONG != SIZEOF_VOID_P # error "Sorry, your platform is not supported at all." # error "Psyco currently requires sizeof(long)==sizeof(void*)." #endif #define INITIAL_STACK_DEPTH 4 /* anything >0 and a multiple of 4 */ /***************************************************************/ /*** Condition Codes (a.k.a. the processor 'flags' register) ***/ /* return a new vinfo_t *meaning `in the processor flags, true if ', as an integer 0 or 1. The source of the vinfo_t *is compile-time if cc is CC_ALWAYS_TRUE/FALSE, and virtual-time otherwise. */ vinfo_t *psyco_vinfo_condition(PsycoObject *po, condition_code_t cc); /* ivm only: */ VirtualTimeSource psyco_source_condition(condition_code_t cc); /* if 'source' comes from psyco_vinfo_condition(), return its ; otherwise return CC_ALWAYS_FALSE. */ #if HAVE_CCREG condition_code_t psyco_vsource_cc(Source source); void psyco_resolved_cc(PsycoObject *po, condition_code_t cc_known_true); #else # define psyco_vsource_cc(src) CC_ALWAYS_FALSE #endif /***************************************************************/ /*** Read/write memory ***/ /* access the data word at address 'nv_ptr + offset + (rt_vindex<refcount1_flags & SkFlagPyObj) != 0) { /* XXX we get a reference from the code. Implement freeing such references together with code buffers. */ sk_incref(sk); } return sk->value; } #endif /*****************************************************************/ /*** Calling C functions ***/ /* A generic way of emitting the call to a C function. For maximal performance you can also directly use the macros CALL_C_FUNCTION()&co. in encoding.h. 'arguments' is a string describing the following arguments of psyco_generic_call(). Each argument to the C function to call comes from a 'vinfo_t*' structure, excepted when it is known to be compile-time, in which case a 'long' or 'PyObject*' can be passed instead. In 'arguments' the characters are interpreted as follows: l an immediate 'long' or 'PyObject*' value v a 'vinfo_t*' value r a run-time 'vinfo_t*' value passed as a reference a a 'vinfo_array_t*' used by the C function as output buffer A same as 'a', but the C function creates new references 'r' means that the C function wants to get a reference to a single-word value (typically it is an output argument). The run-time value is pushed in the stack if it is just in a register. Incompatible with CfPure. 'a' means that the C function gets a pointer to a buffer capable of containing as many words as specified by the array count. psyco_generic_call() fills the array with run-time vinfo_ts representing the output values. */ vinfo_t *psyco_generic_call(PsycoObject *po, void* c_function, int flags, const char* arguments, ...); /* if the C function has no side effect it can be called at compile-time if all its arguments are compile-time. Use CfPure in this case. */ #define CfPure 0x10 /* if the C function returns a long or a PyObject* but not a new reference */ #define CfReturnNormal 0x00 /* default */ /* if the C function returns a new reference */ #define CfReturnRef 0x01 /* if the C function does not return anything or if you are not interested in getting the result in a vinfo_t. psyco_generic_call() returns anything non-NULL (unless there is an error) in this case. */ #define CfNoReturnValue 0x03 #define CfReturnMask 0x0F /* See also the Python-specific flags CfPyErrXxx defined in pycheader.h. */ /* To emit the call to other code blocks emitted by Psyco. 'argsources' gives the run-time sources for the arguments, as specified by psyco_build_frame(). */ vinfo_t *psyco_call_psyco(PsycoObject *po, Source codestart, Source argsources[], int argcount, struct stack_frame_info_s* finfo); PSY_INLINE int get_arguments_count(vinfo_array_t* vlocals) { int retpos = getstack(vlocals->items[INDEX_LOC_CONTINUATION]->source); extra_assert(retpos != RunTime_StackNone); return (retpos-(INITIAL_STACK_DEPTH+sizeof(long))) / sizeof(long); } /* Emit the code to mark the presence of an inlined frame */ void psyco_inline_enter(PsycoObject *po); void psyco_inline_exit (PsycoObject *po); /*****************************************************************/ /*** Emit common instructions ***/ /* Returns a condition code for: "'vi' is not null". Warning, when a function returns a condition code it must be used immediately, before there is any chance for new code to be emitted. If you are unsure, use psyco_vinfo_condition() to turn the condition code into a 0 or 1 integer. */ condition_code_t integer_non_null(PsycoObject *po, vinfo_t *vi); /* Same as above, but consumes the reference on 'vi'. Also checks if 'vi==NULL' and returns CC_ERROR in this case. */ condition_code_t integer_NON_NULL(PsycoObject *po, vinfo_t *vi); /* Instructions with an 'ovf' parameter will check for overflow if 'ovf' is true. They return NULL if an overflow is detected. */ vinfo_t *integer_add (PsycoObject *po, vinfo_t *v1, vinfo_t *v2, bool ovf); /* 'unsafe': optimize by silently assuming no overflow is possible */ vinfo_t *integer_add_i(PsycoObject *po, vinfo_t *v1, long value2, bool unsafe); vinfo_t *integer_sub (PsycoObject *po, vinfo_t *v1, vinfo_t *v2, bool ovf); /*XXX implement me vinfo_t *integer_sub_i(PsycoObject *po, vinfo_t *v1, long value2);*/ vinfo_t *integer_mul (PsycoObject *po, vinfo_t *v1, vinfo_t *v2, bool ovf); vinfo_t *integer_mul_i(PsycoObject *po, vinfo_t *v1, long value2); vinfo_t *integer_or (PsycoObject *po, vinfo_t *v1, vinfo_t *v2); vinfo_t *integer_xor (PsycoObject *po, vinfo_t *v1, vinfo_t *v2); vinfo_t *integer_and (PsycoObject *po, vinfo_t *v1, vinfo_t *v2); /* signed */ vinfo_t *integer_rshift (PsycoObject *po, vinfo_t *v1, vinfo_t *v2); /* signed */ vinfo_t *integer_rshift_i(PsycoObject *po, vinfo_t *v1, long counter); /* unsigned */ vinfo_t *integer_urshift_i(PsycoObject *po, vinfo_t *v1, long counter); vinfo_t *integer_inv (PsycoObject *po, vinfo_t *v1); vinfo_t *integer_neg (PsycoObject *po, vinfo_t *v1, bool ovf); vinfo_t *integer_abs (PsycoObject *po, vinfo_t *v1, bool ovf); /* Comparison: 'py_op' is one of Python's rich comparison numbers Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE optionally together with COMPARE_UNSIGNED, CHEAT_MAXINT. */ condition_code_t integer_cmp (PsycoObject *po, vinfo_t *v1, vinfo_t *v2, int py_op); condition_code_t integer_cmp_i(PsycoObject *po, vinfo_t *v1, long value2, int py_op); #define COMPARE_UNSIGNED 8 #define CHEAT_MAXINT 16 /* assume only a constant can be exactly LONG_MIN or LONG_MAX */ #define COMPARE_BASE_MASK 7 #define COMPARE_OP_MASK 15 /* Return one of two constants, depending on the condition code */ vinfo_t *integer_conditional(PsycoObject *po, condition_code_t cc, long immed_true, long immed_false); /* make a run-time copy of a vinfo_t */ vinfo_t *make_runtime_copy(PsycoObject *po, vinfo_t *v); PSY_INLINE int intlog2(long value) { int counter = 0; while ((1<