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_variable(): global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_Variable_getset_table', []) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef(name, cu.add_simple_getter('gcc_Variable_get_%s' % name, 'PyGccVariable', c_expression), None, doc) add_simple_getter('decl', 'gcc_python_make_wrapper_tree(self->var->decl)', 'The declaration of this variable, as a gcc.Tree') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'gcc_VariableType', localname = 'Variable', tp_name = 'gcc.Variable', tp_dealloc = 'gcc_python_wrapper_dealloc', struct_name = 'PyGccVariable', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, #tp_repr = '(reprfunc)gcc_Variable_repr', #tp_str = '(reprfunc)gcc_Variable_repr', ) 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) { return PyGccString_FromString(gcc_location_get_filename(self->loc)); } """) 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_in_system_header_at(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_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_param(): # # Generate the gcc.Parameter class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccParameter_getset_table', [], identifier_prefix='PyGccParameter', typename='PyGccParameter') def add_simple_getter(name, c_expression, doc): getsettable.add_simple_getter(cu, name, c_expression, doc) add_simple_getter('option', 'PyGccStringOrNone(PARAM_INFO(self).option)', "(string) The name used with the `--param <name>=<value>' switch to set this value") add_simple_getter('default_value', 'PyGccInt_FromLong(PARAM_INFO(self).default_value)', "(int/long)") add_simple_getter('min_value', 'PyGccInt_FromLong(PARAM_INFO(self).min_value)', "(int/long) The minimum acceptable value") add_simple_getter('max_value', 'PyGccInt_FromLong(PARAM_INFO(self).max_value)', "(int/long) The maximum acceptable value, if greater than min_value") add_simple_getter('help', 'PyGccStringOrNone(PARAM_INFO(self).help)', "(string) A short description of the option.") # "current_value": getter = cu.add_simple_getter('PyGccParameter_get_current_value', 'PyGccParameter', 'PyGccInt_FromLong(PARAM_VALUE(self->param_num))') setter = cu.add_simple_int_setter('PyGccParameter_set_current_value', 'PyGccParameter', 'current_value', 'global_options.x_param_values[self->param_num] = PyGccInt_AsLong(value)') #FIXME getsettable.add_gsdef('current_value', getter, setter, "(int/long)") cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccParameter_TypeObj', localname = 'Parameter', tp_name = 'gcc.Parameter', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccParameter', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, #tp_repr = '(reprfunc)PyGccParameter_repr', #tp_str = '(reprfunc)PyGccParameter_str', ) 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_option(): # # Generate the gcc.Option class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccOption_getset_table', [], identifier_prefix='PyGccOption', typename='PyGccOption') def add_simple_getter(name, c_expression, doc): getsettable.add_simple_getter(cu, name, c_expression, doc) add_simple_getter('text', 'PyGccStringOrNone(PyGcc_option_to_cl_option(self)->opt_text)', '(string) The command-line text used to set this option') add_simple_getter('help', 'PyGccStringOrNone(PyGcc_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(PyGcc_option_to_cl_option(self)->flags & %s)' % flag, helptext) getsettable.add_gsdef('is_enabled', 'PyGccOption_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 = 'PyGccOption_TypeObj', localname = 'Option', tp_name = 'gcc.Option', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccOption', tp_init = 'PyGccOption_init', tp_getset = getsettable.identifier, tp_repr = '(reprfunc)PyGccOption_repr', #tp_str = '(reprfunc)PyGccOption_str', #tp_richcompare = 'PyGccOption_richcompare' ) 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('PyGccBasicBlock_getset_table', [PyGetSetDef('preds', 'PyGccBasicBlock_get_preds', None, 'The list of predecessor gcc.Edge instances leading into this block'), PyGetSetDef('succs', 'PyGccBasicBlock_get_succs', None, 'The list of successor gcc.Edge instances leading out of this block'), PyGetSetDef('gimple', 'PyGccBasicBlock_get_gimple', 'PyGccBasicBlock_set_gimple', 'The list of gcc.Gimple instructions, if appropriate for this pass, or None'), PyGetSetDef('phi_nodes', 'PyGccBasicBlock_get_phi_nodes', None, 'The list of gcc.GimplePhi phoney functions, if appropriate for this pass, or None'), PyGetSetDef('rtl', 'PyGccBasicBlock_get_rtl', None, 'The list of gcc.Rtl instructions, if appropriate for this pass, or None'), ], identifier_prefix='PyGccBasicBlock', typename='PyGccBasicBlock') getsettable.add_simple_getter(cu, 'index', 'PyGccInt_FromLong(gcc_cfg_block_get_index(self->bb))', None) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccBasicBlock_TypeObj', localname = 'BasicBlock', tp_name = 'gcc.BasicBlock', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccBasicBlock', tp_new = 'PyType_GenericNew', tp_repr = '(reprfunc)PyGccBasicBlock_repr', #tp_str = '(reprfunc)PyGccBasicBlock_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 = 'PyGcc%s_TypeObj' % cc, localname = cc, tp_name = 'gcc.%s' % cc, tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccPass', tp_new = 'PyType_GenericNew', tp_init = 'PyGcc%s_init' % cc, tp_base = '&PyGccPass_TypeObj', 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_callgraph_node(): # # Generate the gcc.CallgraphNode class: # global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('gcc_CallgraphNode_getset_table', [], identifier_prefix='gcc_CallgraphNode', typename='PyGccCallgraphNode') # FIXME: add getters getsettable.add_simple_getter(cu, 'decl', 'gcc_python_make_wrapper_tree(self->node->decl)', 'The gcc.FunctionDecl for this node') getsettable.add_gsdef('callees', 'gcc_CallgraphNode_get_callees', None, 'The function calls made by this function, as a list of gcc.CallgraphEdge') getsettable.add_gsdef('callers', 'gcc_CallgraphNode_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 = 'gcc_CallgraphNodeType', localname = 'CallgraphNode', tp_name = 'gcc.CallgraphNode', struct_name = 'PyGccCallgraphNode', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, tp_repr = '(reprfunc)gcc_CallgraphNode_repr', tp_str = '(reprfunc)gcc_CallgraphNode_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_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_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="gcc_GimpleStructType%sType" % cc, localname="GimpleStructType" + cc, tp_name="gcc.GimpleStructType%s" % cc, tp_dealloc="gcc_python_wrapper_dealloc", struct_name="PyGccGimple", tp_new="PyType_GenericNew", tp_base="&gcc_GimpleType", # tp_getset = getsettable.identifier, # tp_repr = '(reprfunc)gcc_Gimple_repr', # tp_str = '(reprfunc)gcc_Gimple_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_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_rich_location(): # # Generate the gcc.RichLocation class: # # class rich_location was added to libcpp in gcc 6. GCC_VERSION = get_gcc_version() if GCC_VERSION < 6000: return 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_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_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_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 "PyGcc%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", "PyGccTree_New(gcc_addr_expr_get_operand(PyGccTree_as_gcc_addr_expr(self)))", "The operand of this expression, as a gcc.Tree", ) if cc == "StringCst": add_simple_getter( "constant", "PyGccString_FromString(gcc_string_constant_get_char_ptr(PyGccTree_as_gcc_string_constant(self)))", "The actual value of this constant, as a str", ) tp_repr = "(reprfunc)PyGccStringConstant_repr" if cc == "IntegerCst": getsettable.add_gsdef( "constant", "PyGccIntegerConstant_get_constant", None, "The actual value of this constant, as an int/long", ) number_methods = PyNumberMethods("PyGccIntegerConstant_number_methods") tp_as_number = number_methods.identifier number_methods.nb_int = "PyGccIntegerConstant_get_constant" cu.add_defn(number_methods.c_defn()) tp_repr = "(reprfunc)PyGccIntegerConstant_repr" if cc == "RealCst": getsettable.add_gsdef( "constant", "PyGccRealCst_get_constant", None, "The actual value of this constant, as a float" ) tp_repr = "(reprfunc)PyGccRealCst_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.inner) & TYPE_QUAL_%s)" % qual.upper(), "Boolean: does this type have the '%s' modifier?" % qual, ) add_simple_getter( "%s_equivalent" % qual, "PyGccTree_New(gcc_private_make_tree(build_qualified_type(self->t.inner, TYPE_QUAL_%s)))" % qual.upper(), "The gcc.Type for the %s version of this type" % qual, ) if tree_type.SYM == "RECORD_TYPE": add_simple_getter( "const", "PyBool_FromLong(TYPE_READONLY(self->t.inner))", "Boolean: does this type have the 'const' modifier?", ) if tree_type.SYM == "INTEGER_TYPE": add_simple_getter( "unsigned", "PyBool_FromLong(gcc_integer_type_is_unsigned(PyGccTree_as_gcc_integer_type(self)))", "Boolean: True for 'unsigned', False for 'signed'", ) add_complex_getter("signed_equivalent", "The gcc.IntegerType for the signed version of this type") add_complex_getter("unsigned_equivalent", "The gcc.IntegerType for the unsigned version of this type") add_simple_getter( "max_value", "PyGccTree_New(gcc_integer_constant_as_gcc_tree(gcc_integer_type_get_max_value(PyGccTree_as_gcc_integer_type(self))))", "The maximum possible value for this type, as a gcc.IntegerCst", ) add_simple_getter( "min_value", "PyGccTree_New(gcc_integer_constant_as_gcc_tree(gcc_integer_type_get_min_value(PyGccTree_as_gcc_integer_type(self))))", "The minimum possible value for this type, as a gcc.IntegerCst", ) tp_repr = "(reprfunc)PyGccIntegerType_repr" if tree_type.SYM in ("INTEGER_TYPE", "REAL_TYPE", "FIXED_POINT_TYPE"): prefix = "gcc_%s" % tree_type.SYM.lower() add_simple_getter( "precision", "PyGccInt_FromLong(%s_get_precision(PyGccTree_as_%s(self)))" % (prefix, prefix), "The precision of this type in bits, as an int (e.g. 32)", ) if tree_type.SYM in ("POINTER_TYPE", "ARRAY_TYPE", "VECTOR_TYPE"): prefix = "gcc_%s" % tree_type.SYM.lower() add_simple_getter( "dereference", ("PyGccTree_New(gcc_type_as_gcc_tree(%s_get_dereference(PyGccTree_as_%s(self))))" % (prefix, prefix)), "The gcc.Type that this type points to'", ) if tree_type.SYM == "POINTER_TYPE": tp_repr = "(reprfunc)PyGccPointerType_repr" if tree_type.SYM == "ARRAY_TYPE": add_simple_getter( "range", "PyGccTree_New(gcc_private_make_tree(TYPE_DOMAIN(self->t.inner)))", "The gcc.Type that is the range of this array type", ) if tree_type.SYM == "ARRAY_REF": add_simple_getter( "array", "PyGccTree_New(gcc_array_ref_get_array(PyGccTree_as_gcc_array_ref(self)))", "The gcc.Tree for the array being referenced'", ) add_simple_getter( "index", "PyGccTree_New(gcc_array_ref_get_index(PyGccTree_as_gcc_array_ref(self)))", "The gcc.Tree for index being referenced'", ) tp_repr = "(reprfunc)PyGccArrayRef_repr" if tree_type.SYM == "COMPONENT_REF": add_simple_getter( "target", "PyGccTree_New(gcc_component_ref_get_target(PyGccTree_as_gcc_component_ref(self)))", "The gcc.Tree that for the container of the field'", ) add_simple_getter( "field", "PyGccTree_New(gcc_component_ref_get_field(PyGccTree_as_gcc_component_ref(self)))", "The gcc.FieldDecl for the field within the target'", ) tp_repr = "(reprfunc)PyGccComponentRef_repr" if tree_type.SYM == "MEM_REF": add_simple_getter( "operand", "PyGccTree_New(gcc_mem_ref_get_operand(PyGccTree_as_gcc_mem_ref(self)))", "The gcc.Tree that for the pointer expression'", ) if tree_type.SYM == "BIT_FIELD_REF": add_simple_getter( "operand", "PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 0)))", "The gcc.Tree for the structure or union expression", ) add_simple_getter( "num_bits", "PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 1)))", "The number of bits being referenced, as a gcc.IntegerCst", ) add_simple_getter( "position", "PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 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", "PyGcc_TreeListFromChain(TYPE_FIELDS(self->t.inner))", "The fields of this type" ) add_simple_getter( "methods", "PyGcc_TreeListFromChain(TYPE_METHODS(self->t.inner))", "The methods of this type" ) if tree_type.SYM == "IDENTIFIER_NODE": add_simple_getter( "name", "PyGccStringOrNone(IDENTIFIER_POINTER(self->t.inner))", "The name of this gcc.IdentifierNode, as a string", ) tp_repr = "(reprfunc)PyGccIdentifierNode_repr" if tree_type.SYM == "VAR_DECL": add_simple_getter( "initial", "PyGccTree_New(gcc_constructor_as_gcc_tree(gcc_var_decl_get_initial(PyGccTree_as_gcc_var_decl(self))))", "The initial value for this variable as a gcc.Constructor, or None", ) add_simple_getter( "static", "PyBool_FromLong(gcc_var_decl_is_static(PyGccTree_as_gcc_var_decl(self)))", "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", "PyGccBlock_New(gcc_translation_unit_decl_get_block(PyGccTree_as_gcc_translation_unit_decl(self)))", "The gcc.Block for this namespace", ) add_simple_getter( "language", "PyGccString_FromString(gcc_translation_unit_decl_get_language(PyGccTree_as_gcc_translation_unit_decl(self)))", "The source language of this translation unit, as a string", ) if tree_type.SYM == "BLOCK": add_simple_getter( "vars", "PyGcc_TreeListFromChain(BLOCK_VARS(self->t.inner))", "The list of gcc.Tree for the declarations and labels in this block", ) if tree_type.SYM == "NAMESPACE_DECL": add_simple_getter( "alias_of", "PyGccTree_New(gcc_private_make_tree(DECL_NAMESPACE_ALIAS(self->t.inner)))", "None if not an alias, otherwise the gcc.NamespaceDecl we alias", ) add_simple_getter( "declarations", "PyGccNamespaceDecl_declarations(self->t.inner)", "The list of gcc.Declarations within this namespace", ) add_simple_getter( "namespaces", "PyGccNamespaceDecl_namespaces(self->t.inner)", "The list of gcc.NamespaceDecl objects and gcc.TypeDecl of Unions nested in this namespace", ) methods.add_method( "lookup", "(PyCFunction)PyGccNamespaceDecl_lookup", "METH_VARARGS|METH_KEYWORDS", "Look up the given string within this namespace", ) methods.add_method( "unalias", "(PyCFunction)PyGccNamespaceDecl_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", "PyGccTypeDecl_get_pointer", None, "The gcc.PointerType representing '(this_type *)'" ) if tree_type.SYM == "FUNCTION_TYPE": getsettable.add_gsdef( "argument_types", "PyGccFunction_TypeObj_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", "PyGccMethodType_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", "PyGccFunctionDecl_get_fullname", None, "C++ only: the full name of this function declaration", ) add_simple_getter( "function", "PyGccFunction_New(gcc_private_make_function(DECL_STRUCT_FUNCTION(self->t.inner)))", "The gcc.Function (or None) for this declaration", ) add_simple_getter( "arguments", "PyGcc_TreeListFromChain(DECL_ARGUMENTS(self->t.inner))", "List of gcc.ParmDecl" ) add_simple_getter( "result", "PyGccTree_New(gcc_private_make_tree(DECL_RESULT_FLD(self->t.inner)))", "The gcc.ResultDecl for the return value", ) getsettable.add_gsdef( "callgraph_node", "PyGccFunctionDecl_get_callgraph_node", None, "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.inner))" % attr.upper(), None ) if tree_type.SYM == "SSA_NAME": # c.f. "struct GTY(()) tree_ssa_name": add_simple_getter( "var", "PyGccTree_New(gcc_ssa_name_get_var(PyGccTree_as_gcc_ssa_name(self)))", "The variable being referenced'", ) add_simple_getter( "def_stmt", "PyGccGimple_New(gcc_ssa_name_get_def_stmt(PyGccTree_as_gcc_ssa_name(self)))", "The gcc.Gimple statement which defines this SSA name'", ) add_simple_getter( "version", "PyGccInt_FromLong(gcc_ssa_name_get_version(PyGccTree_as_gcc_ssa_name(self)))", "The SSA version number of this SSA name'", ) tp_repr = "(reprfunc)PyGccSsaName_repr" if tree_type.SYM == "TREE_LIST": # c.f. "struct GTY(()) tree_list": tp_repr = "(reprfunc)PyGccTreeList_repr" if tree_type.SYM == "CASE_LABEL_EXPR": add_simple_getter( "low", "PyGccTree_New(gcc_case_label_expr_get_low(PyGccTree_as_gcc_case_label_expr(self)))", "The low value of the case label, as a gcc.Tree (or None for the default)", ) add_simple_getter( "high", "PyGccTree_New(gcc_case_label_expr_get_high(PyGccTree_as_gcc_case_label_expr(self)))", "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", "PyGccTree_New(gcc_label_decl_as_gcc_tree(gcc_case_label_expr_get_target(PyGccTree_as_gcc_case_label_expr(self))))", "The target of the case label, as a gcc.LabelDecl", ) tp_repr = "(reprfunc)PyGccCaseLabelExpr_repr" cu.add_defn(getsettable.c_defn()) cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject( identifier="PyGcc%s_TypeObj" % 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(" &PyGcc%s_TypeObj, /* %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("PyGcc_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*)&PyGcc%s_TypeObj) {\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* PyGcc_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* PyGcc_autogenerated_tree_type_for_tree(gcc_tree t, int borrow_ref) { enum tree_code code = TREE_CODE(t.inner); /* printf("code:%i\\n", code); */ return PyGcc_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 == 'PyGccTree_TypeObj': continue # Strip off the "PyGcc" prefix and "_TypeObj" suffix: localname = code_type[5:-8] 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='&PyGccTree_TypeObj', tp_getset=getsettable.identifier, tp_methods=methods.identifier) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef( name, cu.add_simple_getter('PyGcc%s_get_%s' % (localname, name), 'PyGccTree', c_expression), None, doc) if localname == 'Declaration': cu.add_defn(""" PyObject * PyGccDeclaration_get_name(struct PyGccTree *self, void *closure) { if (DECL_NAME(self->t.inner)) { return PyGccString_FromString(IDENTIFIER_POINTER (DECL_NAME (self->t.inner))); } Py_RETURN_NONE; } static PyObject * PyGccDeclaration_get_location(struct PyGccTree *self, void *closure) { return PyGccLocation_New(gcc_decl_get_location(PyGccTree_as_gcc_decl(self))); } """) getsettable.add_gsdef('name', 'PyGccDeclaration_get_name', None, 'The name of this declaration (string)') getsettable.add_gsdef('location', 'PyGccDeclaration_get_location', None, 'The gcc.Location for this declaration') add_simple_getter( 'is_artificial', 'PyBool_FromLong(gcc_decl_is_artificial(PyGccTree_as_gcc_decl(self)))', "Is this a compiler-generated entity?") add_simple_getter( 'is_builtin', 'PyBool_FromLong(gcc_decl_is_builtin(PyGccTree_as_gcc_decl(self)))', "Is this declaration built in by the compiler?") pytype.tp_repr = '(reprfunc)PyGccDeclaration_repr' if localname == 'Type': add_simple_getter( 'name', 'PyGccTree_New(gcc_type_get_name(PyGccTree_as_gcc_type(self)))', "The name of the type as a gcc.Tree, or None") add_simple_getter( 'pointer', 'PyGccPointerType_New(gcc_type_get_pointer(PyGccTree_as_gcc_type(self)))', "The gcc.PointerType representing '(this_type *)'") getsettable.add_gsdef('attributes', 'PyGccType_get_attributes', None, 'The user-defined attributes on this type') getsettable.add_gsdef('sizeof', 'PyGccType_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 PyGccTree_New(gcc_private_make_tree(%s)); } """ % ('PyGccType_get_%s' % typename, c_expr_for_node)) if typename == 'size_t': desc = typename else: desc = typename.replace('_', ' ') methods.add_method( '%s' % typename, 'PyGccType_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] # std_types = [ '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' ] if GCCPLUGINS_API_VERSION < 5000: # int128 seems to have gone away in # 9f75f0266e3611513f196c898088e2712a71eaf4, discussed at # https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01396.html std_types += ['itk_int128', 'itk_unsigned_int128'] for std_type in std_types: # strip off the "itk_" prefix assert std_type.startswith('itk_') stddef = std_type[4:] #add_simple_getter(stddef, # 'PyGccTree_New(gcc_private_make_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', 'PyGccTree_New(gcc_unary_get_operand(PyGccTree_as_gcc_unary(self)))', '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', ( 'PyGccLocation_New(gcc_%s_get_location(PyGccTree_as_gcc_%s(self)))' % (localname.lower(), localname.lower())), "The source location of this expression") methods.add_method( 'get_symbol', 'PyGccTree_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_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()
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_tree(): # # Generate the gcc.Tree class: # global modinit_preinit global modinit_postinit cu.add_defn(""" static PyObject * PyGccTree_get_type(struct PyGccTree *self, void *closure) { return PyGccTree_New(gcc_private_make_tree(TREE_TYPE(self->t.inner))); } static PyObject * PyGccTree_get_addr(struct PyGccTree *self, void *closure) { return PyLong_FromVoidPtr(self->t.inner); } """) getsettable = PyGetSetDefTable('PyGccTree_getset_table', [PyGetSetDef('type', 'PyGccTree_get_type', None, 'Instance of gcc.Tree giving the type of the node'), PyGetSetDef('addr', 'PyGccTree_get_addr', None, 'The address of the underlying GCC object in memory'), PyGetSetDef('str_no_uid', 'PyGccTree_get_str_no_uid', None, 'A string representation of this object, like str(), but without including any internal UID')], identifier_prefix='PyGccTree', typename='PyGccTree') cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGccTree_TypeObj', localname = 'Tree', tp_name = 'gcc.Tree', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccTree', tp_new = 'PyType_GenericNew', tp_getset = 'PyGccTree_getset_table', tp_hash = '(hashfunc)PyGccTree_hash', tp_str = '(reprfunc)PyGccTree_str', tp_richcompare = 'PyGccTree_richcompare') methods = PyMethodTable('PyGccTree_methods', []) methods.add_method('debug', 'PyGccTree_debug', 'METH_VARARGS', "Dump the tree to stderr") cu.add_defn(""" PyObject* PyGccTree_debug(PyObject *self, PyObject *args) { PyGccTree *tree_obj; /* FIXME: type checking */ tree_obj = (PyGccTree *)self; debug_tree(tree_obj->t.inner); 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_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 == "PyGccTree_TypeObj": continue # Strip off the "PyGcc" prefix and "_TypeObj" suffix: localname = code_type[5:-8] 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="&PyGccTree_TypeObj", tp_getset=getsettable.identifier, tp_methods=methods.identifier, ) def add_simple_getter(name, c_expression, doc): getsettable.add_gsdef( name, cu.add_simple_getter("PyGcc%s_get_%s" % (localname, name), "PyGccTree", c_expression), None, doc ) if localname == "Declaration": cu.add_defn( """ PyObject * PyGccDeclaration_get_name(struct PyGccTree *self, void *closure) { if (DECL_NAME(self->t.inner)) { return PyGccString_FromString(IDENTIFIER_POINTER (DECL_NAME (self->t.inner))); } Py_RETURN_NONE; } static PyObject * PyGccDeclaration_get_location(struct PyGccTree *self, void *closure) { return PyGccLocation_New(gcc_decl_get_location(PyGccTree_as_gcc_decl(self))); } """ ) getsettable.add_gsdef("name", "PyGccDeclaration_get_name", None, "The name of this declaration (string)") getsettable.add_gsdef( "location", "PyGccDeclaration_get_location", None, "The gcc.Location for this declaration" ) add_simple_getter( "is_artificial", "PyBool_FromLong(gcc_decl_is_artificial(PyGccTree_as_gcc_decl(self)))", "Is this a compiler-generated entity?", ) add_simple_getter( "is_builtin", "PyBool_FromLong(gcc_decl_is_builtin(PyGccTree_as_gcc_decl(self)))", "Is this declaration built in by the compiler?", ) pytype.tp_repr = "(reprfunc)PyGccDeclaration_repr" if localname == "Type": add_simple_getter( "name", "PyGccTree_New(gcc_type_get_name(PyGccTree_as_gcc_type(self)))", "The name of the type as a gcc.Tree, or None", ) add_simple_getter( "pointer", "PyGccPointerType_New(gcc_type_get_pointer(PyGccTree_as_gcc_type(self)))", "The gcc.PointerType representing '(this_type *)'", ) getsettable.add_gsdef( "attributes", "PyGccType_get_attributes", None, "The user-defined attributes on this type" ) getsettable.add_gsdef("sizeof", "PyGccType_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 PyGccTree_New(gcc_private_make_tree(%s)); } """ % ("PyGccType_get_%s" % typename, c_expr_for_node) ) if typename == "size_t": desc = typename else: desc = typename.replace("_", " ") methods.add_method( "%s" % typename, "PyGccType_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] # std_types = [ "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", ] if GCCPLUGINS_API_VERSION < 5000: # int128 seems to have gone away in # 9f75f0266e3611513f196c898088e2712a71eaf4, discussed at # https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01396.html std_types += ["itk_int128", "itk_unsigned_int128"] for std_type in std_types: # strip off the "itk_" prefix assert std_type.startswith("itk_") stddef = std_type[4:] # add_simple_getter(stddef, # 'PyGccTree_New(gcc_private_make_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", "PyGccTree_New(gcc_unary_get_operand(PyGccTree_as_gcc_unary(self)))", "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", ( "PyGccLocation_New(gcc_%s_get_location(PyGccTree_as_gcc_%s(self)))" % (localname.lower(), localname.lower()) ), "The source location of this expression", ) methods.add_method( "get_symbol", "PyGccTree_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_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 'PyGcc%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', 'PyGccTree_New(gcc_addr_expr_get_operand(PyGccTree_as_gcc_addr_expr(self)))', 'The operand of this expression, as a gcc.Tree') if cc == 'StringCst': add_simple_getter('constant', 'PyGccString_FromString(gcc_string_constant_get_char_ptr(PyGccTree_as_gcc_string_constant(self)))', 'The actual value of this constant, as a str') tp_repr = '(reprfunc)PyGccStringConstant_repr' if cc == 'IntegerCst': getsettable.add_gsdef('constant', 'PyGccIntegerConstant_get_constant', None, 'The actual value of this constant, as an int/long') number_methods = PyNumberMethods('PyGccIntegerConstant_number_methods') tp_as_number = number_methods.identifier number_methods.nb_int = 'PyGccIntegerConstant_get_constant' cu.add_defn(number_methods.c_defn()) tp_repr = '(reprfunc)PyGccIntegerConstant_repr' if cc == 'RealCst': getsettable.add_gsdef('constant', 'PyGccRealCst_get_constant', None, 'The actual value of this constant, as a float') tp_repr = '(reprfunc)PyGccRealCst_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.inner) & TYPE_QUAL_%s)' % qual.upper(), "Boolean: does this type have the '%s' modifier?" % qual) add_simple_getter('%s_equivalent' % qual, 'PyGccTree_New(gcc_private_make_tree(build_qualified_type(self->t.inner, TYPE_QUALS(self->t.inner) | TYPE_QUAL_%s)))' % qual.upper(), 'The gcc.Type for the %s version of this type' % qual) add_simple_getter('unqualified_equivalent', 'PyGccTree_New(gcc_private_make_tree(build_qualified_type(self->t.inner, 0)))', 'The gcc.Type for the unqualified version of this type') if tree_type.SYM == 'RECORD_TYPE': add_simple_getter('const', 'PyBool_FromLong(TYPE_READONLY(self->t.inner))', "Boolean: does this type have the 'const' modifier?") if tree_type.SYM == 'INTEGER_TYPE': add_simple_getter('unsigned', 'PyBool_FromLong(gcc_integer_type_is_unsigned(PyGccTree_as_gcc_integer_type(self)))', "Boolean: True for 'unsigned', False for 'signed'") add_complex_getter('signed_equivalent', 'The gcc.IntegerType for the signed version of this type') add_complex_getter('unsigned_equivalent', 'The gcc.IntegerType for the unsigned version of this type') add_simple_getter('max_value', 'PyGccTree_New(gcc_integer_constant_as_gcc_tree(gcc_integer_type_get_max_value(PyGccTree_as_gcc_integer_type(self))))', 'The maximum possible value for this type, as a gcc.IntegerCst') add_simple_getter('min_value', 'PyGccTree_New(gcc_integer_constant_as_gcc_tree(gcc_integer_type_get_min_value(PyGccTree_as_gcc_integer_type(self))))', 'The minimum possible value for this type, as a gcc.IntegerCst') tp_repr = '(reprfunc)PyGccIntegerType_repr' if tree_type.SYM in ('INTEGER_TYPE', 'REAL_TYPE', 'FIXED_POINT_TYPE'): prefix = 'gcc_%s' % tree_type.SYM.lower() add_simple_getter('precision', 'PyGccInt_FromLong(%s_get_precision(PyGccTree_as_%s(self)))' % (prefix, prefix), 'The precision of this type in bits, as an int (e.g. 32)') if tree_type.SYM in ('POINTER_TYPE', 'ARRAY_TYPE', 'VECTOR_TYPE'): prefix = 'gcc_%s' % tree_type.SYM.lower() add_simple_getter('dereference', ('PyGccTree_New(gcc_type_as_gcc_tree(%s_get_dereference(PyGccTree_as_%s(self))))' % (prefix, prefix)), "The gcc.Type that this type points to'") if tree_type.SYM == 'POINTER_TYPE': tp_repr = '(reprfunc)PyGccPointerType_repr' if tree_type.SYM == 'ARRAY_TYPE': add_simple_getter('range', 'PyGccTree_New(gcc_private_make_tree(TYPE_DOMAIN(self->t.inner)))', "The gcc.Type that is the range of this array type") if tree_type.SYM == 'ARRAY_REF': add_simple_getter('array', 'PyGccTree_New(gcc_array_ref_get_array(PyGccTree_as_gcc_array_ref(self)))', "The gcc.Tree for the array being referenced'") add_simple_getter('index', 'PyGccTree_New(gcc_array_ref_get_index(PyGccTree_as_gcc_array_ref(self)))', "The gcc.Tree for index being referenced'") tp_repr = '(reprfunc)PyGccArrayRef_repr' if tree_type.SYM == 'COMPONENT_REF': add_simple_getter('target', 'PyGccTree_New(gcc_component_ref_get_target(PyGccTree_as_gcc_component_ref(self)))', "The gcc.Tree that for the container of the field'") add_simple_getter('field', 'PyGccTree_New(gcc_component_ref_get_field(PyGccTree_as_gcc_component_ref(self)))', "The gcc.FieldDecl for the field within the target'") tp_repr = '(reprfunc)PyGccComponentRef_repr' if tree_type.SYM == 'MEM_REF': add_simple_getter('operand', 'PyGccTree_New(gcc_mem_ref_get_operand(PyGccTree_as_gcc_mem_ref(self)))', "The gcc.Tree that for the pointer expression'") if tree_type.SYM == 'BIT_FIELD_REF': add_simple_getter('operand', 'PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 0)))', "The gcc.Tree for the structure or union expression") add_simple_getter('num_bits', 'PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 1)))', "The number of bits being referenced, as a gcc.IntegerCst") add_simple_getter('position', 'PyGccTree_New(gcc_private_make_tree(TREE_OPERAND(self->t.inner, 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', 'PyGcc_GetFields(self)', "The fields of this type") add_simple_getter('methods', 'PyGcc_GetMethods(self)', "The methods of this type") if tree_type.SYM == 'ENUMERAL_TYPE': add_simple_getter('values', 'PyGcc_TreeMakeListOfPairsFromTreeListChain(TYPE_VALUES(self->t.inner))', "The values of this type") if tree_type.SYM == 'IDENTIFIER_NODE': add_simple_getter('name', 'PyGccStringOrNone(IDENTIFIER_POINTER(self->t.inner))', "The name of this gcc.IdentifierNode, as a string") tp_repr = '(reprfunc)PyGccIdentifierNode_repr' if tree_type.SYM == 'VAR_DECL': add_simple_getter('initial', 'PyGccTree_New(gcc_constructor_as_gcc_tree(gcc_var_decl_get_initial(PyGccTree_as_gcc_var_decl(self))))', "The initial value for this variable as a gcc.Constructor, or None") add_simple_getter('static', 'PyBool_FromLong(gcc_var_decl_is_static(PyGccTree_as_gcc_var_decl(self)))', "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', 'PyGccBlock_New(gcc_translation_unit_decl_get_block(PyGccTree_as_gcc_translation_unit_decl(self)))', "The gcc.Block for this namespace") add_simple_getter('language', 'PyGccString_FromString(gcc_translation_unit_decl_get_language(PyGccTree_as_gcc_translation_unit_decl(self)))', "The source language of this translation unit, as a string") if tree_type.SYM == 'BLOCK': add_simple_getter('vars', 'PyGcc_TreeListFromChain(BLOCK_VARS(self->t.inner))', "The list of gcc.Tree for the declarations and labels in this block") if tree_type.SYM == 'NAMESPACE_DECL': add_simple_getter('alias_of', 'PyGccTree_New(gcc_private_make_tree(DECL_NAMESPACE_ALIAS(self->t.inner)))', "None if not an alias, otherwise the gcc.NamespaceDecl we alias") add_simple_getter('declarations', 'PyGccNamespaceDecl_declarations(self->t.inner)', 'The list of gcc.Declarations within this namespace') add_simple_getter('namespaces', 'PyGccNamespaceDecl_namespaces(self->t.inner)', 'The list of gcc.NamespaceDecl objects and gcc.TypeDecl of Unions nested in this namespace') methods.add_method('lookup', '(PyCFunction)PyGccNamespaceDecl_lookup', 'METH_VARARGS|METH_KEYWORDS', "Look up the given string within this namespace") methods.add_method('unalias', '(PyCFunction)PyGccNamespaceDecl_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', 'PyGccTypeDecl_get_pointer', None, "The gcc.PointerType representing '(this_type *)'") getsettable.add_gsdef('original_type', 'PyGccTypeDecl_get_original_type', None, "The gcc.Type from which this type was typedef'd from.'") if tree_type.SYM == 'FUNCTION_TYPE': getsettable.add_gsdef('argument_types', 'PyGccFunction_TypeObj_get_argument_types', None, "A tuple of gcc.Type instances, representing the argument types of this function type") getsettable.add_gsdef('is_variadic', 'PyGccFunction_TypeObj_is_variadic', None, "Boolean: is this function variadic") if tree_type.SYM == 'METHOD_TYPE': getsettable.add_gsdef('argument_types', 'PyGccMethodType_get_argument_types', None, "A tuple of gcc.Type instances, representing the argument types of this method type") getsettable.add_gsdef('is_variadic', 'PyGccMethodType_is_variadic', None, "Boolean: is this method variadic") if tree_type.SYM == 'FUNCTION_DECL': getsettable.add_gsdef('fullname', 'PyGccFunctionDecl_get_fullname', None, 'C++ only: the full name of this function declaration') add_simple_getter('function', 'PyGccFunction_New(gcc_private_make_function(DECL_STRUCT_FUNCTION(self->t.inner)))', 'The gcc.Function (or None) for this declaration') add_simple_getter('arguments', 'PyGcc_TreeListFromChain(DECL_ARGUMENTS(self->t.inner))', 'List of gcc.ParmDecl') add_simple_getter('result', 'PyGccTree_New(gcc_private_make_tree(DECL_RESULT_FLD(self->t.inner)))', 'The gcc.ResultDecl for the return value') getsettable.add_gsdef('callgraph_node', 'PyGccFunctionDecl_get_callgraph_node', None, '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.inner))' % attr.upper(), None) if tree_type.SYM == 'SSA_NAME': # c.f. "struct GTY(()) tree_ssa_name": add_simple_getter('var', 'PyGccTree_New(gcc_ssa_name_get_var(PyGccTree_as_gcc_ssa_name(self)))', "The variable being referenced'") add_simple_getter('def_stmt', 'PyGccGimple_New(gcc_ssa_name_get_def_stmt(PyGccTree_as_gcc_ssa_name(self)))', "The gcc.Gimple statement which defines this SSA name'") add_simple_getter('version', 'PyGccInt_FromLong(gcc_ssa_name_get_version(PyGccTree_as_gcc_ssa_name(self)))', "The SSA version number of this SSA name'") tp_repr = '(reprfunc)PyGccSsaName_repr' if tree_type.SYM == 'TREE_LIST': # c.f. "struct GTY(()) tree_list": tp_repr = '(reprfunc)PyGccTreeList_repr' if tree_type.SYM == 'CASE_LABEL_EXPR': add_simple_getter('low', 'PyGccTree_New(gcc_case_label_expr_get_low(PyGccTree_as_gcc_case_label_expr(self)))', "The low value of the case label, as a gcc.Tree (or None for the default)") add_simple_getter('high', 'PyGccTree_New(gcc_case_label_expr_get_high(PyGccTree_as_gcc_case_label_expr(self)))', "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', 'PyGccTree_New(gcc_label_decl_as_gcc_tree(gcc_case_label_expr_get_target(PyGccTree_as_gcc_case_label_expr(self))))', "The target of the case label, as a gcc.LabelDecl") tp_repr = '(reprfunc)PyGccCaseLabelExpr_repr' cu.add_defn(getsettable.c_defn()) cu.add_defn(methods.c_defn()) pytype = PyGccWrapperTypeObject(identifier = 'PyGcc%s_TypeObj' % 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(' &PyGcc%s_TypeObj, /* %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('PyGcc_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*)&PyGcc%s_TypeObj) {\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* PyGcc_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* PyGcc_autogenerated_tree_type_for_tree(gcc_tree t, int borrow_ref) { enum tree_code code = TREE_CODE(t.inner); /* printf("code:%i\\n", code); */ return PyGcc_autogenerated_tree_type_for_tree_code(code, borrow_ref); } """)
def generate_tree(): # # Generate the gcc.Tree class: # global modinit_preinit global modinit_postinit cu.add_defn( """ static PyObject * PyGccTree_get_type(struct PyGccTree *self, void *closure) { return PyGccTree_New(gcc_private_make_tree(TREE_TYPE(self->t.inner))); } static PyObject * PyGccTree_get_addr(struct PyGccTree *self, void *closure) { return PyLong_FromVoidPtr(self->t.inner); } """ ) getsettable = PyGetSetDefTable( "PyGccTree_getset_table", [ PyGetSetDef("type", "PyGccTree_get_type", None, "Instance of gcc.Tree giving the type of the node"), PyGetSetDef("addr", "PyGccTree_get_addr", None, "The address of the underlying GCC object in memory"), PyGetSetDef( "str_no_uid", "PyGccTree_get_str_no_uid", None, "A string representation of this object, like str(), but without including any internal UID", ), ], identifier_prefix="PyGccTree", typename="PyGccTree", ) cu.add_defn(getsettable.c_defn()) pytype = PyGccWrapperTypeObject( identifier="PyGccTree_TypeObj", localname="Tree", tp_name="gcc.Tree", tp_dealloc="PyGccWrapper_Dealloc", struct_name="PyGccTree", tp_new="PyType_GenericNew", tp_getset="PyGccTree_getset_table", tp_hash="(hashfunc)PyGccTree_hash", tp_str="(reprfunc)PyGccTree_str", tp_richcompare="PyGccTree_richcompare", ) methods = PyMethodTable("PyGccTree_methods", []) methods.add_method("debug", "PyGccTree_debug", "METH_VARARGS", "Dump the tree to stderr") cu.add_defn( """ PyObject* PyGccTree_debug(PyObject *self, PyObject *args) { PyGccTree *tree_obj; /* FIXME: type checking */ tree_obj = (PyGccTree *)self; debug_tree(tree_obj->t.inner); 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_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)); } """) 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'), 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'), ], 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()) methods = PyMethodTable('PyGccLocation_methods', []) 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', 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_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_pass(): global modinit_preinit global modinit_postinit getsettable = PyGetSetDefTable('PyGccPass_getset_table', [], identifier_prefix='PyGccPass', typename='PyGccPass') getsettable.add_simple_getter(cu, 'name', 'PyGccString_FromString(self->pass->name)', 'Name of the pass') getsettable.add_simple_getter(cu, 'next', 'PyGccPass_New(self->pass->next)', 'The next gcc.Pass after this one, or None') getsettable.add_simple_getter(cu, 'sub', 'PyGccPass_New(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, 'PyGccInt_FromLong(self->pass->%s)' % field, None) getsettable.add_simple_getter(cu, 'static_pass_number', 'PyGccInt_FromLong(self->pass->static_pass_number)', 'Number of this pass, used as a fragment of the dump file name') getsettable.add_gsdef('dump_enabled', 'PyGccPass_get_dump_enabled', 'PyGccPass_set_dump_enabled', '(boolean) Is dumping enabled for this pass?') cu.add_defn(getsettable.c_defn()) methods = PyMethodTable('PyGccPass_methods', []) methods.add_method('get_roots', 'PyGccPass_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)PyGccPass_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)PyGccPass_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)PyGccPass_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)PyGccPass_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 = 'PyGccPass_TypeObj', localname = 'Pass', tp_name = 'gcc.Pass', tp_dealloc = 'PyGccWrapper_Dealloc', struct_name = 'PyGccPass', tp_new = 'PyType_GenericNew', tp_getset = getsettable.identifier, tp_repr = '(reprfunc)PyGccPass_repr', tp_str = '(reprfunc)PyGccPass_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()