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()
Example #10
0
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()
Example #28
0
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()
Example #30
0
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()
Example #32
0
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()