def generate_variable(): global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccVariable_getset_table', []) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef( name, cu.add_simple_getter('PyGccVariable_get_%s' % name, 'PyGccVariable', c_expression), None, doc) add_simple_getter('decl', 'PyGccTree_New(gcc_variable_get_decl(self->var))', 'The declaration of this variable, as a gcc.Tree') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='PyGccVariable_TypeObj', localname='Variable', tp_name='gcc.Variable', tp_dealloc='PyGccWrapper_Dealloc', struct_name='PyGccVariable', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, #tp_repr = '(reprfunc)PyGccVariable_repr', #tp_str = '(reprfunc)PyGccVariable_repr', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_rich_location(): # # Generate the gcc.RichLocation class: # global modinit_preinit global modinit_postinit methods = PyMethodTable('PyGccRichLocation_methods', []) methods.add_method('add_fixit_replace', '(PyCFunction)PyGccRichLocation_add_fixit_replace', 'METH_VARARGS | METH_KEYWORDS', "FIXME") cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject( identifier='PyGccRichLocation_TypeObj', localname='RichLocation', tp_name='gcc.RichLocation', struct_name='PyGccRichLocation', tp_new='PyType_GenericNew', tp_init='(initproc)PyGccRichLocation_init', #tp_getset = getsettable.identifier, #tp_hash = '(hashfunc)PyGccRichLocation_hash', #tp_repr = '(reprfunc)PyGccRichLocation_repr', #tp_str = '(reprfunc)PyGccRichLocation_str', tp_methods=methods.identifier, #tp_richcompare = 'PyGccRichLocation_richcompare', tp_dealloc='PyGccWrapper_Dealloc') cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_concrete_rtx_code_subclasses(): global modinit_preinit global modinit_postinit for expr_type in rtl_expr_types: cc = expr_type.camel_cased_string() getsettable = None if getsettable: cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGcc%s_TypeObj' % cc, localname = cc, tp_name = 'gcc.%s' % cc, struct_name = 'PyGccRtl', tp_new = 'PyType_GenericNew', tp_base = ('&PyGccRtlClassType%s_TypeObj' % camel_case(expr_type.CLASS)), tp_getset = getsettable.identifier if getsettable else None, tp_repr = '(reprfunc)PyGccRtl_repr', tp_str = '(reprfunc)PyGccRtl_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_param(): # # Generate the gcc.Parameter class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_Parameter_getset_table', [], identifier_prefix='gcc_Parameter', typename='PyGccParameter') def add_simple_getter(name, c_expression, doc): getsettable.add_simple_getter(cu, name, c_expression, doc) add_simple_getter( 'option', 'gcc_python_string_or_none(PARAM_INFO(self).option)', "(string) The name used with the `--param <name>=<value>' switch to set this value" ) add_simple_getter( 'default_value', 'gcc_python_int_from_long(PARAM_INFO(self).default_value)', "(int/long)") add_simple_getter('min_value', 'gcc_python_int_from_long(PARAM_INFO(self).min_value)', "(int/long) The minimum acceptable value") add_simple_getter( 'max_value', 'gcc_python_int_from_long(PARAM_INFO(self).max_value)', "(int/long) The maximum acceptable value, if greater than min_value") add_simple_getter('help', 'gcc_python_string_or_none(PARAM_INFO(self).help)', "(string) A short description of the option.") # "current_value": getter = cu.add_simple_getter( 'gcc_Parameter_get_current_value', 'PyGccParameter', 'gcc_python_int_from_long(PARAM_VALUE(self->param_num))') setter = cu.add_simple_int_setter( 'gcc_Parameter_set_current_value', 'PyGccParameter', 'current_value', 'global_options.x_param_values[self->param_num] = gcc_python_int_as_long(value)' ) #FIXME getsettable.add_gsdef('current_value', getter, setter, "(int/long)") cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_ParameterType', localname='Parameter', tp_name='gcc.Parameter', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccParameter', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, #tp_repr = '(reprfunc)gcc_Parameter_repr', #tp_str = '(reprfunc)gcc_Parameter_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_option(): # # Generate the gcc.Option class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_Option_getset_table', [], identifier_prefix='gcc_Option', typename='PyGccOption') def add_simple_getter(name, c_expression, doc): getsettable.add_simple_getter(cu, name, c_expression, doc) add_simple_getter( 'text', 'gcc_python_string_or_none(gcc_python_option_to_cl_option(self)->opt_text)', '(string) The command-line text used to set this option') add_simple_getter( 'help', 'gcc_python_string_or_none(gcc_python_option_to_cl_option(self)->help)', '(string) The help text shown for this option') for flag, helptext in ( ('CL_WARNING', '(bool) Does this option control a warning message?'), ('CL_OPTIMIZATION', '(bool) Does this option control an optimization?'), ('CL_DRIVER', '(bool) Is this a driver option?'), ('CL_TARGET', '(bool) Is this a target-specific option?'), ): add_simple_getter( 'is_%s' % flag[3:].lower(), 'PyBool_FromLong(gcc_python_option_to_cl_option(self)->flags & %s)' % flag, helptext) getsettable.add_gsdef( 'is_enabled', 'gcc_Option_is_enabled', None, 'True/False for whether or not this option is enabled, raising a ' 'NotImplementedError for options for which the plugin cannot tell') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_OptionType', localname='Option', tp_name='gcc.Option', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccOption', tp_init='gcc_Option_init', tp_getset=getsettable.identifier, tp_repr='(reprfunc)gcc_Option_repr', #tp_str = '(reprfunc)gcc_Option_str', #tp_richcompare = 'gcc_Option_richcompare' ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_function(): # # Generate the gcc.Function class: # global modinit_preinit global modinit_postinit cu.add_defn( "\n" "static PyObject *\n" "PyGccFunction_get_cfg(struct PyGccFunction *self, void *closure)\n" "{\n" " return PyGccCfg_New(gcc_function_get_cfg(self->fun));\n" "}\n" "\n") getsettable = PyGetSetDefTable('PyGccFunction_getset_table', [ PyGetSetDef( 'cfg', 'PyGccFunction_get_cfg', None, 'Instance of gcc.Cfg for this function (or None for early passes)' ), ], identifier_prefix='PyGccFunction', typename='PyGccFunction') getsettable.add_simple_getter( cu, 'decl', 'PyGccTree_New(gcc_function_decl_as_gcc_tree(gcc_function_get_decl(self->fun)))', 'The declaration of this function, as a gcc.FunctionDecl instance') getsettable.add_simple_getter( cu, 'local_decls', 'VEC_tree_as_PyList(self->fun.inner->local_decls)', "List of gcc.VarDecl for the function's local variables") getsettable.add_simple_getter( cu, 'funcdef_no', 'PyGccInt_FromLong(gcc_function_get_index(self->fun))', 'Function sequence number for profiling, debugging, etc.') getsettable.add_simple_getter( cu, 'start', 'PyGccLocation_New(gcc_function_get_start(self->fun))', 'Location of the start of the function') getsettable.add_simple_getter( cu, 'end', 'PyGccLocation_New(gcc_function_get_end(self->fun))', 'Location of the end of the function') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='PyGccFunction_TypeObj', localname='Function', tp_name='gcc.Function', tp_dealloc='PyGccWrapper_Dealloc', struct_name='PyGccFunction', tp_new='PyType_GenericNew', tp_repr='(reprfunc)PyGccFunction_repr', tp_str='(reprfunc)PyGccFunction_repr', tp_hash='(hashfunc)PyGccFunction_hash', tp_richcompare='PyGccFunction_richcompare', tp_getset=getsettable.identifier, ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_location(): # # Generate the gcc.Location class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * gcc_Location_get_file(struct PyGccLocation *self, void *closure) { return gcc_python_string_from_string(LOCATION_FILE(self->loc)); } """) cu.add_defn(""" static PyObject * gcc_Location_get_line(struct PyGccLocation *self, void *closure) { return gcc_python_int_from_long(LOCATION_LINE(self->loc)); } """) cu.add_defn(""" static PyObject * gcc_Location_get_column(struct PyGccLocation *self, void *closure) { expanded_location exploc = expand_location(self->loc); return gcc_python_int_from_long(exploc.column); } """) getsettable = PyGetSetDefTable('gcc_Location_getset_table', [ PyGetSetDef('file', 'gcc_Location_get_file', None, 'Name of the source file'), PyGetSetDef('line', 'gcc_Location_get_line', None, 'Line number within source file'), PyGetSetDef('column', 'gcc_Location_get_column', None, 'Column number within source file'), ]) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier='gcc_LocationType', localname='Location', tp_name='gcc.Location', struct_name='PyGccLocation', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, tp_repr='(reprfunc)gcc_Location_repr', tp_str='(reprfunc)gcc_Location_str', tp_richcompare='gcc_Location_richcompare', tp_dealloc='gcc_python_wrapper_dealloc') cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_function(): # # Generate the gcc.Function class: # global modinit_preinit global modinit_postinit cu.add_defn( "\n" "static PyObject *\n" "gcc_Function_get_cfg(struct PyGccFunction *self, void *closure)\n" "{\n" " return gcc_python_make_wrapper_cfg(self->fun->cfg);\n" "}\n" "\n") getsettable = PyGetSetDefTable('gcc_Function_getset_table', [ PyGetSetDef( 'cfg', 'gcc_Function_get_cfg', None, 'Instance of gcc.Cfg for this function (or None for early passes)' ), ], identifier_prefix='gcc_Function', typename='PyGccFunction') getsettable.add_simple_getter( cu, 'decl', 'gcc_python_make_wrapper_tree(self->fun->decl)', 'The declaration of this function, as a gcc.FunctionDecl instance') getsettable.add_simple_getter( cu, 'local_decls', 'VEC_tree_as_PyList(self->fun->local_decls)', "List of gcc.VarDecl for the function's local variables") getsettable.add_simple_getter( cu, 'funcdef_no', 'gcc_python_int_from_long(self->fun->funcdef_no)', 'Function sequence number for profiling, debugging, etc.') getsettable.add_simple_getter( cu, 'start', 'gcc_python_make_wrapper_location(self->fun->function_start_locus)', 'Location of the start of the function') getsettable.add_simple_getter( cu, 'end', 'gcc_python_make_wrapper_location(self->fun->function_end_locus)', 'Location of the end of the function') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_FunctionType', localname='Function', tp_name='gcc.Function', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccFunction', tp_new='PyType_GenericNew', tp_repr='(reprfunc)gcc_Function_repr', tp_str='(reprfunc)gcc_Function_repr', tp_getset=getsettable.identifier, ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_edge(): # # Generate the gcc.Edge class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccEdge_getset_table', [PyGetSetDef('src', cu.add_simple_getter('PyGccEdge_get_src', 'PyGccEdge', 'PyGccBasicBlock_New(gcc_cfg_edge_get_src(self->e))'), None, 'The source gcc.BasicBlock of this edge'), PyGetSetDef('dest', cu.add_simple_getter('PyGccEdge_get_dest', 'PyGccEdge', 'PyGccBasicBlock_New(gcc_cfg_edge_get_dest(self->e))'), None, 'The destination gcc.BasicBlock of this edge')], identifier_prefix = 'PyGccEdge', typename = 'PyGccEdge') # We only expose the subset of the flags exposed by gcc-c-api for attrname, flaggetter in [('true_value', 'is_true_value'), ('false_value', 'is_false_value'), ('loop_exit', 'is_loop_exit'), ('can_fallthru', 'get_can_fallthru'), ('complex', 'is_complex'), ('eh', 'is_eh'), ]: getsettable.add_simple_getter(cu, attrname, 'PyBool_FromLong(gcc_cfg_edge_%s(self->e))' % flaggetter, None) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccEdge_TypeObj', localname = 'Edge', tp_name = 'gcc.Edge', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccEdge', tp_new = 'PyType_GenericNew', #tp_repr = '(reprfunc)PyGccEdge_repr', #tp_str = '(reprfunc)PyGccEdge_repr', tp_getset = getsettable.identifier, ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_basic_block(): # # Generate the gcc.BasicBlock class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_BasicBlock_getset_table', [ PyGetSetDef( 'preds', 'gcc_BasicBlock_get_preds', None, 'The list of predecessor gcc.Edge instances leading into this block' ), PyGetSetDef( 'succs', 'gcc_BasicBlock_get_succs', None, 'The list of successor gcc.Edge instances leading out of this block' ), PyGetSetDef( 'gimple', 'gcc_BasicBlock_get_gimple', None, 'The list of gcc.Gimple instructions, if appropriate for this pass, or None' ), PyGetSetDef( 'phi_nodes', 'gcc_BasicBlock_get_phi_nodes', None, 'The list of gcc.GimplePhi phoney functions, if appropriate for this pass, or None' ), PyGetSetDef( 'rtl', 'gcc_BasicBlock_get_rtl', None, 'The list of gcc.Rtl instructions, if appropriate for this pass, or None' ), ], identifier_prefix='gcc_BasicBlock', typename='PyGccBasicBlock') getsettable.add_simple_getter(cu, 'index', 'gcc_python_int_from_long(self->bb->index)', None) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_BasicBlockType', localname='BasicBlock', tp_name='gcc.BasicBlock', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccBasicBlock', tp_new='PyType_GenericNew', #tp_repr = '(reprfunc)gcc_BasicBlock_repr', #tp_str = '(reprfunc)gcc_BasicBlock_repr', tp_getset=getsettable.identifier, ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_edge(): # # Generate the gcc.Edge class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_Edge_getset_table', [ PyGetSetDef( 'src', cu.add_simple_getter( 'gcc_Edge_get_src', 'PyGccEdge', 'gcc_python_make_wrapper_basic_block(self->e->src)'), None, 'The source gcc.BasicBlock of this edge'), PyGetSetDef( 'dest', cu.add_simple_getter( 'gcc_Edge_get_dest', 'PyGccEdge', 'gcc_python_make_wrapper_basic_block(self->e->dest)'), None, 'The destination gcc.BasicBlock of this edge') ], identifier_prefix='gcc_Edge', typename='PyGccEdge') for flag in ('EDGE_FALLTHRU', 'EDGE_ABNORMAL', 'EDGE_ABNORMAL_CALL', 'EDGE_EH', 'EDGE_FAKE', 'EDGE_DFS_BACK', 'EDGE_CAN_FALLTHRU', 'EDGE_IRREDUCIBLE_LOOP', 'EDGE_SIBCALL', 'EDGE_LOOP_EXIT', 'EDGE_TRUE_VALUE', 'EDGE_FALSE_VALUE', 'EDGE_EXECUTABLE', 'EDGE_CROSSING'): assert flag.startswith('EDGE_') flagname = flag[5:].lower() getsettable.add_simple_getter( cu, flagname, 'PyBool_FromLong(self->e->flags & %s)' % flag, 'Boolean, corresponding to flag %s' % flag) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_EdgeType', localname='Edge', tp_name='gcc.Edge', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccEdge', tp_new='PyType_GenericNew', #tp_repr = '(reprfunc)gcc_Edge_repr', #tp_str = '(reprfunc)gcc_Edge_repr', tp_getset=getsettable.identifier, ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_cfg(): # # Generate the gcc.Cfg class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccCfg_getset_table', [PyGetSetDef('basic_blocks', 'PyGccCfg_get_basic_blocks', None, 'The list of gcc.BasicBlock instances in this graph'), PyGetSetDef('entry', cu.add_simple_getter('PyGccCfg_get_entry', 'PyGccCfg', 'PyGccBasicBlock_New(gcc_cfg_get_entry(self->cfg))'), None, 'The initial gcc.BasicBlock in this graph'), PyGetSetDef('exit', cu.add_simple_getter('PyGccCfg_get_exit', 'PyGccCfg', 'PyGccBasicBlock_New(gcc_cfg_get_exit(self->cfg))'), None, 'The final gcc.BasicBlock in this graph'), ]) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccCfg_TypeObj', localname = 'Cfg', tp_name = 'gcc.Cfg', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccCfg', tp_new = 'PyType_GenericNew', #tp_repr = '(reprfunc)PyGccCfg_repr', #tp_str = '(reprfunc)PyGccCfg_repr', tp_getset = getsettable.identifier, ) methods = PyMethodTable('PyGccCfg_methods', []) methods.add_method('get_block_for_label', 'PyGccCfg_get_block_for_label', 'METH_VARARGS', "Given a gcc.LabelDecl, get the corresponding gcc.BasicBlock") cu.add_defn(methods.c_defn()) pytype.tp_methods = methods.identifier cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_intermediate_rtx_class_subclasses(): global modinit_preinit global modinit_postinit for rtx_class in enum_rtx_class: cc = camel_case(rtx_class) pytype = PyGccWrapperTypeObject(identifier = 'PyGccRtlClassType%s_TypeObj' % cc, localname = 'RtlClassType' + cc, tp_name = 'gcc.%s' % cc, struct_name = 'PyGccRtl', tp_new = 'PyType_GenericNew', tp_base = '&PyGccRtl_TypeObj', #tp_getset = getsettable.identifier, #tp_repr = '(reprfunc)PyGccRtl_repr', #tp_str = '(reprfunc)PyGccRtl_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_pass_subclasses(): global modinit_preinit global modinit_postinit for opt_pass_type in ('GIMPLE_PASS', 'RTL_PASS', 'SIMPLE_IPA_PASS', 'IPA_PASS'): cc = camel_case(opt_pass_type) pytype = PyGccWrapperTypeObject( identifier='gcc_%sType' % cc, localname=cc, tp_name='gcc.%s' % cc, tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccPass', tp_new='PyType_GenericNew', tp_init='gcc_%s_init' % cc, tp_base='&gcc_PassType', tp_flags='(Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE)') cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_gimple_struct_subclasses(): global modinit_preinit global modinit_postinit for gt in gimple_struct_types: #print gimple_types cc = gt.camel_cased_string() pytype = PyGccWrapperTypeObject(identifier = 'PyGccGimpleStructType%s_TypeObj' % cc, localname = 'GimpleStructType' + cc, tp_name = 'gcc.GimpleStructType%s' % cc, tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccGimple', tp_new = 'PyType_GenericNew', tp_base = '&PyGccGimple_TypeObj', #tp_getset = getsettable.identifier, #tp_repr = '(reprfunc)PyGccGimple_repr', #tp_str = '(reprfunc)PyGccGimple_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_rtl_base_class(): # # Generate the gcc.Rtl class: # global modinit_preinit global modinit_postinit ''' cu.add_defn(""" static PyObject * PyGccRtl_get_block(struct PyGccRtl *self, void *closure) { return PyGccTree_New(rtl_block(self->stmt)); } """) ''' getsettable = PyGetSetDefTable('PyGccRtl_getset_table', []) if GCC_VERSION < 5000: getsettable.add_gsdef('loc', 'PyGccRtl_get_location', None, 'Source code location of this instruction, as a gcc.Location') getsettable.add_gsdef('operands', 'PyGccRtl_get_operands', None, 'Operands of this expression, as a tuple') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccRtl_TypeObj', localname = 'Rtl', tp_name = 'gcc.Rtl', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccRtl', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, tp_repr = '(reprfunc)PyGccRtl_repr', tp_str = '(reprfunc)PyGccRtl_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_callgraph_node(): # # Generate the gcc.CallgraphNode class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccCallgraphNode_getset_table', [], identifier_prefix='PyGccCallgraphNode', typename='PyGccCallgraphNode') # FIXME: add getters getsettable.add_simple_getter( cu, 'decl', 'PyGccTree_New(gcc_function_decl_as_gcc_tree(gcc_cgraph_node_get_decl(self->node)))', 'The gcc.FunctionDecl for this node') getsettable.add_gsdef( 'callees', 'PyGccCallgraphNode_get_callees', None, 'The function calls made by this function, as a list of gcc.CallgraphEdge' ) getsettable.add_gsdef( 'callers', 'PyGccCallgraphNode_get_callers', None, 'The places that call this function, as a list of gcc.CallgraphEdge') cu.add_defn(getsettable.c_defn()) # see gcc/cgraph.c: dump_cgraph_node (FILE *f, struct cgraph_node *node) pytype = PyGccWrapperTypeObject( identifier='PyGccCallgraphNode_TypeObj', localname='CallgraphNode', tp_name='gcc.CallgraphNode', struct_name='PyGccCallgraphNode', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, tp_repr='(reprfunc)PyGccCallgraphNode_repr', tp_str='(reprfunc)PyGccCallgraphNode_str', tp_dealloc='PyGccWrapper_Dealloc', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_callgraph_edge(): # # Generate the gcc.CallgraphEdge class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_CallgraphEdge_getset_table', [], identifier_prefix='gcc_CallgraphEdge', typename='PyGccCallgraphEdge') getsettable.add_simple_getter( cu, 'caller', 'gcc_python_make_wrapper_cgraph_node(self->edge->caller)', 'The function that makes this call, as a gcc.CallgraphNode') getsettable.add_simple_getter( cu, 'callee', 'gcc_python_make_wrapper_cgraph_node(self->edge->callee)', 'The function that is called here, as a gcc.CallgraphNode') getsettable.add_simple_getter( cu, 'call_stmt', 'gcc_python_make_wrapper_gimple(self->edge->call_stmt)', 'The gcc.GimpleCall statememt for the function call') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_CallgraphEdgeType', localname='CallgraphEdge', tp_name='gcc.CallgraphEdge', struct_name='PyGccCallgraphEdge', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, tp_repr='(reprfunc)gcc_CallgraphEdge_repr', tp_str='(reprfunc)gcc_CallgraphEdge_str', tp_dealloc='gcc_python_wrapper_dealloc', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_location(): # # Generate the gcc.Location class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * PyGccLocation_get_file(struct PyGccLocation *self, void *closure) { const char *filename = gcc_location_get_filename(self->loc); if (!filename) { Py_RETURN_NONE; } return PyGccString_FromString(filename); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_line(struct PyGccLocation *self, void *closure) { return PyGccInt_FromLong(gcc_location_get_line(self->loc)); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_column(struct PyGccLocation *self, void *closure) { return PyGccInt_FromLong(gcc_location_get_column(self->loc)); } """) if get_gcc_version() >= 7000: cu.add_defn(""" static PyObject * PyGccLocation_get_caret(struct PyGccLocation *self, void *closure) { return PyGccLocation_New(gcc_location_get_caret(self->loc)); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_start(struct PyGccLocation *self, void *closure) { return PyGccLocation_New(gcc_location_get_start(self->loc)); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_finish(struct PyGccLocation *self, void *closure) { return PyGccLocation_New(gcc_location_get_finish(self->loc)); } """) getsettable = PyGetSetDefTable('PyGccLocation_getset_table', [ PyGetSetDef('file', 'PyGccLocation_get_file', None, 'Name of the source file'), PyGetSetDef('line', 'PyGccLocation_get_line', None, 'Line number within source file'), PyGetSetDef('column', 'PyGccLocation_get_column', None, 'Column number within source file'), ], identifier_prefix='PyGccLocation', typename='PyGccLocation') if get_gcc_version() >= 7000: getsettable.gsdefs += [ PyGetSetDef('caret', 'PyGccLocation_get_caret', None, 'Location of caret'), PyGetSetDef('start', 'PyGccLocation_get_start', None, 'Starting location of range'), PyGetSetDef('finish', 'PyGccLocation_get_finish', None, 'End location of range') ] getsettable.add_simple_getter( cu, 'in_system_header', 'PyBool_FromLong(gcc_location_get_in_system_header(self->loc))', 'Boolean: is this location within a system header?') cu.add_defn(getsettable.c_defn()) methods = PyMethodTable('PyGccLocation_methods', []) if get_gcc_version() >= 5000: methods.add_method('offset_column', '(PyCFunction)PyGccLocation_offset_column', 'METH_VARARGS', "") cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject(identifier='PyGccLocation_TypeObj', localname='Location', tp_name='gcc.Location', struct_name='PyGccLocation', tp_new='PyType_GenericNew', tp_init='(initproc)PyGccLocation_init' if get_gcc_version() >= 7000 else None, tp_getset=getsettable.identifier, tp_hash='(hashfunc)PyGccLocation_hash', tp_repr='(reprfunc)PyGccLocation_repr', tp_str='(reprfunc)PyGccLocation_str', tp_methods=methods.identifier, tp_richcompare='PyGccLocation_richcompare', tp_dealloc='PyGccWrapper_Dealloc') cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_tree(): # # Generate the gcc.Tree class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * gcc_Tree_get_type(struct PyGccTree *self, void *closure) { return gcc_python_make_wrapper_tree(TREE_TYPE(self->t)); } static PyObject * gcc_Tree_get_addr(struct PyGccTree *self, void *closure) { return PyLong_FromVoidPtr(self->t); } """) getsettable = PyGetSetDefTable('gcc_Tree_getset_table', [PyGetSetDef('type', 'gcc_Tree_get_type', None, 'Instance of gcc.Tree giving the type of the node'), PyGetSetDef('addr', 'gcc_Tree_get_addr', None, 'The address of the underlying GCC object in memory'), PyGetSetDef('str_no_uid', 'gcc_Tree_get_str_no_uid', None, 'A string representation of this object, like str(), but without including any internal UID')], identifier_prefix='gcc_Tree', typename='PyGccTree') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'gcc_TreeType', localname = 'Tree', tp_name = 'gcc.Tree', tp_dealloc = 'gcc_python_wrapper_dealloc', struct_name = 'PyGccTree', tp_new = 'PyType_GenericNew', tp_getset = 'gcc_Tree_getset_table', tp_hash = '(hashfunc)gcc_Tree_hash', tp_str = '(reprfunc)gcc_Tree_str', tp_richcompare = 'gcc_Tree_richcompare') methods = PyMethodTable('gcc_Tree_methods', []) methods.add_method('debug', 'gcc_Tree_debug', 'METH_VARARGS', "Dump the tree to stderr") cu.add_defn(""" PyObject* gcc_Tree_debug(PyObject *self, PyObject *args) { PyGccTree *tree_obj; /* FIXME: type checking */ tree_obj = (PyGccTree *)self; debug_tree(tree_obj->t); Py_RETURN_NONE; } """) cu.add_defn(methods.c_defn()) pytype.tp_methods = methods.identifier cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_tree_code_classes(): # Generate all of the concrete gcc.Tree subclasses based on the: # enum tree_code # as subclasses of the above layer: global modinit_preinit global modinit_postinit for tree_type in tree_types: base_type = type_for_code_class[tree_type.TYPE] cc = tree_type.camel_cased_string() getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [], identifier_prefix='gcc_%s' % cc, typename='PyGccTree') tp_as_number = None tp_repr = None tp_str = None methods = PyMethodTable('gcc_%s_methods' % cc, []) def get_getter_identifier(name): return 'gcc_%s_get_%s' % (cc, name) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef(name, cu.add_simple_getter(get_getter_identifier(name), 'PyGccTree', c_expression), None, doc) def add_complex_getter(name, doc): getsettable.add_gsdef(name, get_getter_identifier(name), None, doc) if cc == 'AddrExpr': add_simple_getter('operand', 'gcc_python_make_wrapper_tree(TREE_OPERAND (self->t, 0))', 'The operand of this expression, as a gcc.Tree') if cc == 'StringCst': add_simple_getter('constant', 'gcc_python_string_from_string(TREE_STRING_POINTER(self->t))', 'The actual value of this constant, as a str') tp_repr = '(reprfunc)gcc_StringConstant_repr' if cc == 'IntegerCst': getsettable.add_gsdef('constant', 'gcc_IntegerConstant_get_constant', None, 'The actual value of this constant, as an int/long') number_methods = PyNumberMethods('gcc_IntegerConstant_number_methods') tp_as_number = number_methods.identifier number_methods.nb_int = 'gcc_IntegerConstant_get_constant' cu.add_defn(number_methods.c_defn()) tp_repr = '(reprfunc)gcc_IntegerConstant_repr' if cc == 'RealCst': getsettable.add_gsdef('constant', 'gcc_RealCst_get_constant', None, 'The actual value of this constant, as a float') tp_repr = '(reprfunc)gcc_RealCst_repr' # TYPE_QUALS for various foo_TYPE classes: if tree_type.SYM in ('VOID_TYPE', 'INTEGER_TYPE', 'REAL_TYPE', 'FIXED_POINT_TYPE', 'COMPLEX_TYPE', 'VECTOR_TYPE', 'ENUMERAL_TYPE', 'BOOLEAN_TYPE'): for qual in ('const', 'volatile', 'restrict'): add_simple_getter(qual, 'PyBool_FromLong(TYPE_QUALS(self->t) & TYPE_QUAL_%s)' % qual.upper(), "Boolean: does this type have the '%s' modifier?" % qual) add_simple_getter('%s_equivalent' % qual, 'gcc_python_make_wrapper_tree(build_qualified_type(self->t, TYPE_QUAL_%s))' % qual.upper(), 'The gcc.Type for the %s version of this type' % qual) if tree_type.SYM == 'INTEGER_TYPE': add_simple_getter('unsigned', 'PyBool_FromLong(TYPE_UNSIGNED(self->t))', "Boolean: True for 'unsigned', False for 'signed'") add_simple_getter('signed_equivalent', 'gcc_python_make_wrapper_tree(c_common_signed_type(self->t))', 'The gcc.IntegerType for the signed version of this type') add_simple_getter('unsigned_equivalent', 'gcc_python_make_wrapper_tree(c_common_unsigned_type(self->t))', 'The gcc.IntegerType for the unsigned version of this type') add_simple_getter('max_value', 'gcc_python_make_wrapper_tree(TYPE_MAX_VALUE(self->t))', 'The maximum possible value for this type, as a gcc.IntegerCst') add_simple_getter('min_value', 'gcc_python_make_wrapper_tree(TYPE_MIN_VALUE(self->t))', 'The minimum possible value for this type, as a gcc.IntegerCst') if tree_type.SYM in ('INTEGER_TYPE', 'REAL_TYPE', 'FIXED_POINT_TYPE'): add_simple_getter('precision', 'gcc_python_int_from_long(TYPE_PRECISION(self->t))', 'The precision of this type in bits, as an int (e.g. 32)') if tree_type.SYM in ('POINTER_TYPE', 'ARRAY_TYPE', 'VECTOR_TYPE'): add_simple_getter('dereference', 'gcc_python_make_wrapper_tree(TREE_TYPE(self->t))', "The gcc.Type that this type points to'") if tree_type.SYM == 'ARRAY_TYPE': add_simple_getter('range', 'gcc_python_make_wrapper_tree(TYPE_DOMAIN(self->t))', "The gcc.Type that is the range of this array type") if tree_type.SYM == 'ARRAY_REF': add_simple_getter('array', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 0))', "The gcc.Tree for the array being referenced'") add_simple_getter('index', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 1))', "The gcc.Tree for index being referenced'") if tree_type.SYM == 'COMPONENT_REF': add_simple_getter('target', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 0))', "The gcc.Tree that for the container of the field'") add_simple_getter('field', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 1))', "The gcc.FieldDecl for the field within the target'") if tree_type.SYM == 'MEM_REF': add_simple_getter('operand', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 0))', "The gcc.Tree that for the pointer expression'") if tree_type.SYM == 'BIT_FIELD_REF': add_simple_getter('operand', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 0))', "The gcc.Tree for the structure or union expression") add_simple_getter('num_bits', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 1))', "The number of bits being referenced, as a gcc.IntegerCst") add_simple_getter('position', 'gcc_python_make_wrapper_tree(TREE_OPERAND(self->t, 2))', "The position of the first referenced bit, as a gcc.IntegerCst") if tree_type.SYM in ('RECORD_TYPE', 'UNION_TYPE', 'QUAL_UNION_TYPE'): add_simple_getter('fields', 'gcc_tree_list_from_chain(TYPE_FIELDS(self->t))', "The fields of this type") if tree_type.SYM == 'IDENTIFIER_NODE': add_simple_getter('name', 'gcc_python_string_or_none(IDENTIFIER_POINTER(self->t))', "The name of this gcc.IdentifierNode, as a string") tp_repr = '(reprfunc)gcc_IdentifierNode_repr' if tree_type.SYM == 'VAR_DECL': add_simple_getter('initial', 'gcc_python_make_wrapper_tree(DECL_INITIAL(self->t))', "The initial value for this variable as a gcc.Constructor, or None") add_simple_getter('static', 'PyBool_FromLong(TREE_STATIC(self->t))', "Boolean: is this variable to be allocated with static storage") if tree_type.SYM == 'CONSTRUCTOR': add_complex_getter('elements', "The elements of this constructor, as a list of (index, gcc.Tree) pairs") if tree_type.SYM == 'TRANSLATION_UNIT_DECL': add_simple_getter('block', 'gcc_python_make_wrapper_tree(DECL_INITIAL(self->t))', "The gcc.Block for this namespace") add_simple_getter('language', 'gcc_python_string_from_string(TRANSLATION_UNIT_LANGUAGE(self->t))', "The source language of this translation unit, as a string") if tree_type.SYM == 'BLOCK': add_simple_getter('vars', 'gcc_tree_list_from_chain(BLOCK_VARS(self->t))', "The list of gcc.Tree for the declarations and labels in this block") if tree_type.SYM == 'NAMESPACE_DECL': add_simple_getter('alias_of', 'gcc_python_make_wrapper_tree(DECL_NAMESPACE_ALIAS(self->t))', "None if not an alias, otherwise the gcc.NamespaceDecl we alias") add_simple_getter('declarations', 'gcc_python_namespace_decl_declarations(self->t)', 'The list of gcc.Declarations within this namespace') add_simple_getter('namespaces', 'gcc_python_namespace_decl_namespaces(self->t)', 'The list of gcc.NamespaceDecl objects and gcc.TypeDecl of Unions nested in this namespace') methods.add_method('lookup', '(PyCFunction)gcc_NamespaceDecl_lookup', 'METH_VARARGS|METH_KEYWORDS', "Look up the given string within this namespace") methods.add_method('unalias', '(PyCFunction)gcc_NamespaceDecl_unalias', 'METH_VARARGS|METH_KEYWORDS', "A gcc.NamespaceDecl of this namespace that is not an alias") if tree_type.SYM == 'TYPE_DECL': getsettable.add_gsdef('pointer', 'gcc_TypeDecl_get_pointer', None, "The gcc.PointerType representing '(this_type *)'") if tree_type.SYM == 'FUNCTION_TYPE': getsettable.add_gsdef('argument_types', 'gcc_FunctionType_get_argument_types', None, "A tuple of gcc.Type instances, representing the argument types of this function type") if tree_type.SYM == 'METHOD_TYPE': getsettable.add_gsdef('argument_types', 'gcc_MethodType_get_argument_types', None, "A tuple of gcc.Type instances, representing the argument types of this method type") if tree_type.SYM == 'FUNCTION_DECL': getsettable.add_gsdef('fullname', 'gcc_FunctionDecl_get_fullname', None, 'C++ only: the full name of this function declaration') add_simple_getter('function', 'gcc_python_make_wrapper_function(DECL_STRUCT_FUNCTION(self->t))', 'The gcc.Function (or None) for this declaration') add_simple_getter('arguments', 'gcc_tree_list_from_chain(DECL_ARGUMENTS(self->t))', 'List of gcc.ParmDecl') add_simple_getter('result', 'gcc_python_make_wrapper_tree(DECL_RESULT_FLD(self->t))', 'The gcc.ResultDecl for the return value') add_simple_getter('callgraph_node', 'gcc_python_make_wrapper_cgraph_node(cgraph_get_node(self->t))', 'The gcc.CallgraphNode for this function declaration, or None') for attr in ('public', 'private', 'protected', 'static'): getsettable.add_simple_getter(cu, 'is_%s' % attr, 'PyBool_FromLong(TREE_%s(self->t))' % attr.upper(), None) if tree_type.SYM == 'SSA_NAME': # c.f. "struct GTY(()) tree_ssa_name": add_simple_getter('var', 'gcc_python_make_wrapper_tree(SSA_NAME_VAR(self->t))', "The variable being referenced'") add_simple_getter('def_stmt', 'gcc_python_make_wrapper_gimple(SSA_NAME_DEF_STMT(self->t))', "The gcc.Gimple statement which defines this SSA name'") add_simple_getter('version', 'gcc_python_int_from_long(SSA_NAME_VERSION(self->t))', "The SSA version number of this SSA name'") if tree_type.SYM == 'TREE_LIST': # c.f. "struct GTY(()) tree_list": tp_repr = '(reprfunc)gcc_TreeList_repr' if tree_type.SYM == 'CASE_LABEL_EXPR': add_simple_getter('low', 'gcc_python_make_wrapper_tree(CASE_LOW(self->t))', "The low value of the case label, as a gcc.Tree (or None for the default)") add_simple_getter('high', 'gcc_python_make_wrapper_tree(CASE_HIGH(self->t))', "The high value of the case label, if any, as a gcc.Tree (None for the default and for single-valued case labels)") add_simple_getter('target', 'gcc_python_make_wrapper_tree(CASE_LABEL(self->t))', "The target of the case label, as a gcc.LabelDecl") cu.add_defn(getsettable.c_defn()) cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'gcc_%sType' % cc, localname = cc, tp_name = 'gcc.%s' % cc, struct_name = 'PyGccTree', tp_new = 'PyType_GenericNew', tp_base = '&%s' % base_type, tp_getset = getsettable.identifier, tp_str = tp_str, tp_repr = tp_repr, tp_methods = methods.identifier, ) if tp_as_number: pytype.tp_as_number = '&%s' % tp_as_number cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module() cu.add_defn('\n/* Map from GCC tree codes to PyGccWrapperTypeObject* */\n') cu.add_defn('PyGccWrapperTypeObject *pytype_for_tree_code[] = {\n') for tree_type in tree_types: cu.add_defn(' &gcc_%sType, /* %s */\n' % (tree_type.camel_cased_string(), tree_type.SYM)) cu.add_defn('};\n\n') cu.add_defn('\n/* Map from PyGccWrapperTypeObject* to GCC tree codes*/\n') cu.add_defn('int \n') cu.add_defn('gcc_python_tree_type_object_as_tree_code(PyObject *cls, enum tree_code *out)\n') cu.add_defn('{\n') for tree_type in tree_types: cu.add_defn(' if (cls == (PyObject*)&gcc_%sType) {\n' ' *out = %s; return 0;\n' ' }\n' % (tree_type.camel_cased_string(), tree_type.SYM)) cu.add_defn(' return -1;\n') cu.add_defn('}\n') cu.add_defn(""" PyGccWrapperTypeObject* gcc_python_autogenerated_tree_type_for_tree_code(enum tree_code code, int borrow_ref) { PyGccWrapperTypeObject *result; assert(code >= 0); assert(code < MAX_TREE_CODES); result = pytype_for_tree_code[code]; if (!borrow_ref) { Py_INCREF(result); } return result; } PyGccWrapperTypeObject* gcc_python_autogenerated_tree_type_for_tree(tree t, int borrow_ref) { enum tree_code code = TREE_CODE(t); /* printf("code:%i\\n", code); */ return gcc_python_autogenerated_tree_type_for_tree_code(code, borrow_ref); } """)
def generate_intermediate_tree_classes(): # Generate a "middle layer" of gcc.Tree subclasses, corresponding to most of the # values of # enum_tree_code_class # from GCC's tree.h global modinit_preinit global modinit_postinit for code_type in type_for_code_class.values(): # We've already built the base class: if code_type == 'gcc_TreeType': continue # Strip off the "gcc_" prefix and "Type" suffix: localname = code_type[4:-4] getsettable = PyGetSetDefTable('gcc_%s_getset_table' % localname, []) methods = PyMethodTable('gcc_%s_methods' % localname, []) pytype = PyGccWrapperTypeObject(identifier = code_type, localname = localname, tp_name = 'gcc.%s' % localname, struct_name = 'PyGccTree', tp_new = 'PyType_GenericNew', tp_base = '&gcc_TreeType', tp_getset = getsettable.identifier, tp_methods = methods.identifier) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef(name, cu.add_simple_getter('gcc_%s_get_%s' % (localname, name), 'PyGccTree', c_expression), None, doc) if localname == 'Declaration': cu.add_defn(""" PyObject * gcc_Declaration_get_name(struct PyGccTree *self, void *closure) { if (DECL_NAME(self->t)) { return gcc_python_string_from_string(IDENTIFIER_POINTER (DECL_NAME (self->t))); } Py_RETURN_NONE; } static PyObject * gcc_Declaration_get_location(struct PyGccTree *self, void *closure) { return gcc_python_make_wrapper_location(DECL_SOURCE_LOCATION(self->t)); } """) getsettable.add_gsdef('name', 'gcc_Declaration_get_name', None, 'The name of this declaration (string)') getsettable.add_gsdef('location', 'gcc_Declaration_get_location', None, 'The gcc.Location for this declaration') add_simple_getter('is_artificial', 'PyBool_FromLong(DECL_ARTIFICIAL(self->t))', "Is this a compiler-generated entity?") add_simple_getter('is_builtin', 'PyBool_FromLong(DECL_IS_BUILTIN(self->t))', "Is this declaration built in by the compiler?") pytype.tp_repr = '(reprfunc)gcc_Declaration_repr' if localname == 'Type': add_simple_getter('name', 'gcc_python_make_wrapper_tree(TYPE_NAME(self->t))', "The name of the type as a gcc.Tree, or None") add_simple_getter('pointer', 'gcc_python_make_wrapper_tree(build_pointer_type(self->t))', "The gcc.PointerType representing '(this_type *)'") getsettable.add_gsdef('attributes', 'gcc_Type_get_attributes', None, 'The user-defined attributes on this type') getsettable.add_gsdef('sizeof', 'gcc_Type_get_sizeof', None, 'sizeof() this type, as a gcc.IntegerCst') def add_type(c_expr_for_node, typename): # Expose the given global type node within the gcc.Tree API # # The table is populated by tree.c:build_common_builtin_nodes # but unfortunately this seems to be called after our plugin is # initialized. # # Hence we add them as properties, so that they can be looked up on # demand, rather than trying to look them up once when the module # is set up cu.add_defn(""" PyObject* %s(PyObject *cls, PyObject *args) { return gcc_python_make_wrapper_tree(%s); } """ % ('gcc_Type_get_%s' % typename, c_expr_for_node)) if typename == 'size_t': desc = typename else: desc = typename.replace('_', ' ') methods.add_method('%s' % typename, 'gcc_Type_get_%s' % typename, 'METH_CLASS|METH_NOARGS', "The builtin type '%s' as a gcc.Type (or None at startup before any compilation passes)" % desc) # Add the standard C integer types as properties. # # Tree nodes for the standard C integer types are defined in tree.h by # extern GTY(()) tree integer_types[itk_none]; # with macros to look into it of this form: # #define unsigned_type_node integer_types[itk_unsigned_int] # for std_type in ('itk_char', 'itk_signed_char', 'itk_unsigned_char', 'itk_short', 'itk_unsigned_short', 'itk_int', 'itk_unsigned_int', 'itk_long', 'itk_unsigned_long', 'itk_long_long', 'itk_unsigned_long_long', 'itk_int128', 'itk_unsigned_int128'): # strip off the "itk_" prefix assert std_type.startswith('itk_') stddef = std_type[4:] #add_simple_getter(stddef, # 'gcc_python_make_wrapper_tree(integer_types[%s])' % std_type, # "The builtin type '%s' as a gcc.Type (or None at startup before any compilation passes)" % stddef.replace('_', ' ')) add_type('integer_types[%s]' % std_type, stddef) # Similarly, # extern GTY(()) tree global_trees[TI_MAX]; # holds various nodes, including many with a _TYPE suffix. # Here are some of them: for ti in ('TI_UINT32_TYPE', 'TI_UINT64_TYPE', 'TI_FLOAT_TYPE', 'TI_DOUBLE_TYPE', 'TI_LONG_DOUBLE_TYPE', 'TI_VOID_TYPE', 'TI_SIZE_TYPE'): # strip off the "TI_" prefix and "_TYPE" suffix: assert ti.startswith('TI_') assert ti.endswith('_TYPE') if ti == 'TI_SIZE_TYPE': name = 'size_t' else: name = ti[3:-5].lower() add_type('global_trees[%s]' % ti, name) if localname == 'Unary': add_simple_getter('operand', 'gcc_python_make_wrapper_tree(TREE_OPERAND (self->t, 0))', 'The operand of this expression, as a gcc.Tree') # Corresponds to this gcc/tree.h macro: # #define IS_EXPR_CODE_CLASS(CLASS)\ # ((CLASS) >= tcc_reference && (CLASS) <= tcc_expression) if localname in ('Reference', 'Comparison', 'Unary', 'Binary', 'Statement' 'VlExp', 'Expression'): add_simple_getter('location', 'gcc_python_make_wrapper_location(EXPR_LOCATION(self->t))', "The source location of this expression") methods.add_method('get_symbol', 'gcc_Tree_get_symbol', # they all share the implementation 'METH_CLASS|METH_NOARGS', "FIXME") cu.add_defn(methods.c_defn()) cu.add_defn(getsettable.c_defn()) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_pass(): global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_Pass_getset_table', [], identifier_prefix='gcc_Pass', typename='PyGccPass') getsettable.add_simple_getter( cu, 'name', 'gcc_python_string_from_string(self->pass->name)', 'Name of the pass') getsettable.add_simple_getter( cu, 'next', 'gcc_python_make_wrapper_pass(self->pass->next)', 'The next gcc.Pass after this one, or None') getsettable.add_simple_getter( cu, 'sub', 'gcc_python_make_wrapper_pass(self->pass->sub)', "The first sub-pass (gated by this pass' predicate, if any)") for field in ('properties_required', 'properties_provided', 'properties_destroyed'): getsettable.add_simple_getter( cu, field, 'gcc_python_int_from_long(self->pass->%s)' % field, None) getsettable.add_simple_getter( cu, 'static_pass_number', 'gcc_python_int_from_long(self->pass->static_pass_number)', 'Number of this pass, used as a fragment of the dump file name') getsettable.add_gsdef('dump_enabled', 'gcc_Pass_get_dump_enabled', 'gcc_Pass_set_dump_enabled', '(boolean) Is dumping enabled for this pass?') cu.add_defn(getsettable.c_defn()) methods = PyMethodTable('gcc_Pass_methods', []) methods.add_method( 'get_roots', 'gcc_Pass_get_roots', 'METH_CLASS | METH_VARARGS', "Get a tuple of gcc.Pass instances, the roots of the compilation pass tree" ) methods.add_method( 'get_by_name', '(PyCFunction)gcc_Pass_get_by_name', 'METH_CLASS | METH_VARARGS | METH_KEYWORDS', "Get the gcc.Pass instance for the pass with the given name, raising ValueError if it isn't found" ) methods.add_method( 'register_after', '(PyCFunction)gcc_Pass_register_after', 'METH_VARARGS | METH_KEYWORDS', "Given the name of another pass, register this gcc.Pass to occur immediately after that other pass" ) methods.add_method( 'register_before', '(PyCFunction)gcc_Pass_register_before', 'METH_VARARGS | METH_KEYWORDS', "Given the name of another pass, register this gcc.Pass to occur immediately before that other pass" ) methods.add_method( 'replace', '(PyCFunction)gcc_Pass_replace', 'METH_VARARGS | METH_KEYWORDS', "Given the name of another pass, replace that pass with this gcc.Pass") cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject( identifier='gcc_PassType', localname='Pass', tp_name='gcc.Pass', tp_dealloc='gcc_python_wrapper_dealloc', struct_name='PyGccPass', tp_new='PyType_GenericNew', tp_getset=getsettable.identifier, tp_repr='(reprfunc)gcc_Pass_repr', tp_str='(reprfunc)gcc_Pass_repr', tp_methods=methods.identifier, tp_flags='(Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE)', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_location(): # # Generate the gcc.Location class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * PyGccLocation_get_file(struct PyGccLocation *self, void *closure) { const char *filename = gcc_location_get_filename(self->loc); if (!filename) { Py_RETURN_NONE; } return PyGccString_FromString(filename); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_line(struct PyGccLocation *self, void *closure) { return PyGccInt_FromLong(gcc_location_get_line(self->loc)); } """) cu.add_defn(""" static PyObject * PyGccLocation_get_column(struct PyGccLocation *self, void *closure) { return PyGccInt_FromLong(gcc_location_get_column(self->loc)); } """) getsettable = PyGetSetDefTable('PyGccLocation_getset_table', [PyGetSetDef('file', 'PyGccLocation_get_file', None, 'Name of the source file'), PyGetSetDef('line', 'PyGccLocation_get_line', None, 'Line number within source file'), PyGetSetDef('column', 'PyGccLocation_get_column', None, 'Column number within source file'), ], identifier_prefix='PyGccLocation', typename='PyGccLocation') getsettable.add_simple_getter(cu, 'in_system_header', 'PyBool_FromLong(gcc_location_get_in_system_header(self->loc))', 'Boolean: is this location within a system header?') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccLocation_TypeObj', localname = 'Location', tp_name = 'gcc.Location', struct_name = 'PyGccLocation', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, tp_hash = '(hashfunc)PyGccLocation_hash', tp_repr = '(reprfunc)PyGccLocation_repr', tp_str = '(reprfunc)PyGccLocation_str', tp_richcompare = 'PyGccLocation_richcompare', tp_dealloc = 'PyGccWrapper_Dealloc') cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_gimple(): # # Generate the gcc.Gimple class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * PyGccGimple_get_location(struct PyGccGimple *self, void *closure) { return PyGccLocation_New(gcc_gimple_get_location(self->stmt)); } static PyObject * PyGccGimple_get_block(struct PyGccGimple *self, void *closure) { return PyGccTree_New(gcc_gimple_get_block(self->stmt)); } """) getsettable = PyGetSetDefTable('PyGccGimple_getset_table', [PyGetSetDef('loc', 'PyGccGimple_get_location', None, 'Source code location of this statement, as a gcc.Location'), PyGetSetDef('block', 'PyGccGimple_get_block', None, 'The lexical block holding this statement, as a gcc.Tree'), PyGetSetDef('exprtype', cu.add_simple_getter('PyGccGimple_get_exprtype', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_get_expr_type(self->stmt))'), None, 'The type of the main expression computed by this statement, as a gcc.Tree (which might be gcc.Void_TypeObj)'), PyGetSetDef('str_no_uid', 'PyGccGimple_get_str_no_uid', None, 'A string representation of this statement, like str(), but without including any internal UID'), ]) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccGimple_TypeObj', localname = 'Gimple', tp_name = 'gcc.Gimple', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccGimple', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, tp_repr = '(reprfunc)PyGccGimple_repr', tp_str = '(reprfunc)PyGccGimple_str', tp_hash = '(hashfunc)PyGccGimple_hash', tp_richcompare = 'PyGccGimple_richcompare', tp_flags = 'Py_TPFLAGS_BASETYPE', ) methods = PyMethodTable('PyGccGimple_methods', []) methods.add_method('walk_tree', '(PyCFunction)PyGccGimple_walk_tree', 'METH_VARARGS | METH_KEYWORDS', "Visit all gcc.Tree nodes associated with this statement") cu.add_defn(methods.c_defn()) pytype.tp_methods = methods.identifier cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()
def generate_gimple_subclasses(): global modinit_preinit global modinit_postinit exprcode_getter = PyGetSetDef('exprcode', cu.add_simple_getter('PyGccGimple_get_exprcode', 'PyGccGimple', '(PyObject*)PyGcc_autogenerated_tree_type_for_tree_code(gimple_expr_code(self->stmt.inner), 0)'), None, 'The kind of the expression, as an gcc.Tree subclass (the type itself, not an instance)') rhs_getter = PyGetSetDef('rhs', 'PyGccGimple_get_rhs', None, 'The operands on the right-hand-side of the expression, as a list of gcc.Tree instances') def make_getset_Asm(): getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [exprcode_getter], 'PyGccGimpleAsm', 'PyGccGimple') getsettable.add_simple_getter(cu, 'string', 'PyGccString_FromString(gcc_gimple_asm_get_string(PyGccGimple_as_gcc_gimple_asm(self)))', 'The inline assembler as a string') return getsettable def make_getset_Assign(): return PyGetSetDefTable('gcc_%s_getset_table' % cc, [PyGetSetDef('lhs', cu.add_simple_getter('PyGccGimpleAssign_get_lhs', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_assign_get_lhs(PyGccGimple_as_gcc_gimple_assign(self)))'), None, 'Left-hand-side of the assignment, as a gcc.Tree'), exprcode_getter, rhs_getter, ]) def make_getset_Call(): return PyGetSetDefTable('gcc_%s_getset_table' % cc, [PyGetSetDef('lhs', cu.add_simple_getter('PyGccGimpleCall_get_lhs', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_call_get_lhs(PyGccGimple_as_gcc_gimple_call(self)))'), None, 'Left-hand-side of the call, as a gcc.Tree'), rhs_getter, PyGetSetDef('fn', cu.add_simple_getter('PyGccGimpleCall_get_fn', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_call_get_fn(PyGccGimple_as_gcc_gimple_call(self)))'), None, 'The function being called, as a gcc.Tree'), PyGetSetDef('fndecl', cu.add_simple_getter('PyGccGimpleCall_get_fndecl', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_call_get_fndecl(PyGccGimple_as_gcc_gimple_call(self)))'), None, 'The declaration of the function being called (if any), as a gcc.Tree'), exprcode_getter, PyGetSetDef('args', 'PyGccGimpleCall_get_args', None, 'The arguments for the call, as a list of gcc.Tree'), PyGetSetDef('noreturn', cu.add_simple_getter('PyGccGimpleCall_get_noreturn', 'PyGccGimple', 'PyBool_FromLong(gcc_gimple_call_is_noreturn(PyGccGimple_as_gcc_gimple_call(self)))'), None, 'Has this call been marked as not returning, as a boolean'), ], ) def make_getset_Return(): return PyGetSetDefTable('gcc_%s_getset_table' % cc, [PyGetSetDef('retval', cu.add_simple_getter('PyGccGimpleReturn_get_retval', 'PyGccGimple', 'PyGccTree_New(gcc_gimple_return_get_retval(PyGccGimple_as_gcc_gimple_return(self)))'), None, 'The return value, as a gcc.Tree'), ]) def make_getset_Cond(): getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [exprcode_getter], 'PyGccGimpleCond', 'PyGccGimple') getsettable.add_simple_getter(cu, 'lhs', 'PyGccTree_New(gcc_gimple_cond_get_lhs(PyGccGimple_as_gcc_gimple_cond(self)))', None) getsettable.add_simple_getter(cu, 'rhs', 'PyGccTree_New(gcc_gimple_cond_get_rhs(PyGccGimple_as_gcc_gimple_cond(self)))', None) getsettable.add_simple_getter(cu, 'true_label', 'PyGccTree_New(gcc_gimple_cond_get_true_label(PyGccGimple_as_gcc_gimple_cond(self)))', None) getsettable.add_simple_getter(cu, 'false_label', 'PyGccTree_New(gcc_gimple_cond_get_false_label(PyGccGimple_as_gcc_gimple_cond(self)))', None) return getsettable def make_getset_Phi(): getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [exprcode_getter], 'PyGccGimplePhi', 'PyGccGimple') getsettable.add_simple_getter(cu, 'lhs', 'PyGccTree_New(gcc_gimple_phi_get_result(PyGccGimple_as_gcc_gimple_phi(self)))', None) getsettable.add_gsdef('args', 'PyGccGimplePhi_get_args', None, 'Get a list of (gcc.Tree, gcc.Edge) pairs representing the possible (expr, edge) inputs') # FIXME: should we instead have a dict here? return getsettable def make_getset_Switch(): getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [exprcode_getter], 'PyGccGimpleSwitch', 'PyGccGimple') getsettable.add_simple_getter(cu, 'indexvar', 'PyGccTree_New(gcc_gimple_switch_get_indexvar(PyGccGimple_as_gcc_gimple_switch(self)))', 'Get the index variable used by the switch statement, as a gcc.Tree') getsettable.add_gsdef('labels', 'PyGccGimpleSwitch_get_labels', None, 'Get a list of labels, as a list of gcc.CaseLabelExpr The initial label in the list is always the default.') return getsettable def make_getset_Label(): getsettable = PyGetSetDefTable('gcc_%s_getset_table' % cc, [exprcode_getter], 'PyGccGimpleLabel', 'PyGccGimple') getsettable.add_simple_getter(cu, 'label', 'PyGccTree_New(gcc_label_decl_as_gcc_tree(gcc_gimple_label_get_label(PyGccGimple_as_gcc_gimple_label(self))))', 'Get the underlying gcc.LabelDecl for this statement') return getsettable for gt in gimple_types: cc = gt.camel_cased_string() tp_repr = None getsettable = None if cc == 'GimpleAsm': getsettable = make_getset_Asm() elif cc == 'GimpleAssign': getsettable = make_getset_Assign() elif cc == 'GimpleCall': getsettable = make_getset_Call() elif cc == 'GimpleCond': getsettable = make_getset_Cond() elif cc == 'GimpleReturn': getsettable = make_getset_Return() elif cc == 'GimplePhi': getsettable = make_getset_Phi() elif cc == 'GimpleSwitch': getsettable = make_getset_Switch() elif cc == 'GimpleLabel': getsettable = make_getset_Label() tp_repr = '(reprfunc)PyGccGimpleLabel_repr' if getsettable: cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGcc%s_TypeObj' % cc, localname = cc, tp_name = 'gcc.%s' % cc, tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccGimple', tp_new = 'PyType_GenericNew', tp_base = '&PyGccGimple_TypeObj', tp_getset = getsettable.identifier if getsettable else None, tp_repr = tp_repr, #tp_str = '(reprfunc)PyGccGimple_str', ) cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module()