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_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()