From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- gcc/objc/objc-runtime-shared-support.c | 736 +++++++++++++++++++++++++++++++++ 1 file changed, 736 insertions(+) create mode 100644 gcc/objc/objc-runtime-shared-support.c (limited to 'gcc/objc/objc-runtime-shared-support.c') diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c new file mode 100644 index 000000000..8dca6ccae --- /dev/null +++ b/gcc/objc/objc-runtime-shared-support.c @@ -0,0 +1,736 @@ +/* Support routines shared by all runtimes. + Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Iain Sandoe (partially split from objc-act.c) + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" + +#ifdef OBJCPLUS +#include "cp-tree.h" +#else +#include "c-tree.h" +#include "c-lang.h" +#endif +#include "langhooks.h" +#include "c-family/c-objc.h" +#include "objc-act.h" + +/* When building Objective-C++, we are not linking against the C front-end + and so need to replicate the C tree-construction functions in some way. */ +#ifdef OBJCPLUS +#define OBJCP_REMAP_FUNCTIONS +#include "objcp-decl.h" +#endif /* OBJCPLUS */ + +#include "obstack.h" + +/* These are only used for encoding ivars. */ +extern struct obstack util_obstack; +extern char *util_firstobj; + +/* Hooks for string decls etc. */ +#include "objc-runtime-hooks.h" + +#include "objc-runtime-shared-support.h" + +/* rt_trees identifiers - shared between NeXT implementations. These allow + the FE to tag meta-data in a manner that survives LTO and can be used when + the runtime requires that certain meta-data items appear in particular + named sections. */ +#include "objc-next-metadata-tags.h" +extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX]; + +/* Rather than repeatedly looking up the identifiers, we save them here. */ +tree objc_rt_trees[OCTI_RT_META_MAX]; + +/* For building an objc struct. These might not be used when this file + is compiled as part of obj-c++. */ + +static bool objc_building_struct; +static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED; + +/* Start building a struct for objc. */ + +tree +objc_start_struct (tree name) +{ + gcc_assert (!objc_building_struct); + objc_building_struct = true; + return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info); +} + +/* Finish building a struct for objc. */ + +tree +objc_finish_struct (tree type, tree fieldlist) +{ + gcc_assert (objc_building_struct); + objc_building_struct = false; + return finish_struct (input_location, type, fieldlist, NULL_TREE, + objc_struct_info); +} + +tree +build_sized_array_type (tree base_type, int size) +{ + tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1)); + return build_array_type (base_type, index_type); +} + +/* Create a declaration for field NAME of a given TYPE. */ + +static tree +create_field_decl (tree type, const char *name) +{ + return build_decl (input_location, + FIELD_DECL, get_identifier (name), type); +} + +tree +add_field_decl (tree type, const char *name, tree **chain) +{ + tree field = create_field_decl (type, name); + + if (*chain != NULL) + **chain = field; + *chain = &DECL_CHAIN (field); + + return field; +} + +/* Create a global, static declaration for variable NAME of a given TYPE. The + finish_var_decl() routine will need to be called on it afterwards. */ + +tree +start_var_decl (tree type, const char *name) +{ + tree var = build_decl (input_location, + VAR_DECL, get_identifier (name), type); + TREE_STATIC (var) = 1; + DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */ + DECL_IGNORED_P (var) = 1; + DECL_ARTIFICIAL (var) = 1; + DECL_CONTEXT (var) = NULL_TREE; +#ifdef OBJCPLUS + DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */ +#endif + return var; +} + +/* Finish off the variable declaration created by start_var_decl(). */ + +void +finish_var_decl (tree var, tree initializer) +{ + finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE); +} + +/* Just a handy wrapper for add_objc_string. */ + +tree +build_selector (tree ident) +{ + return convert (objc_selector_type, add_objc_string (ident, meth_var_names)); +} + +/* --- templates --- */ + +/* Set 'objc_super_template' to the data type node for 'struct _objc_super'. + This needs to be done just once per compilation. */ + +/* struct _objc_super { + struct _objc_object *self; + struct _objc_class *super_class; + [or Class cls; for the abi v2] + }; */ + +void +build_super_template (void) +{ + tree decls, *chain = NULL; + + objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER)); + + /* struct _objc_object *self; */ + decls = add_field_decl (objc_object_type, "self", &chain); + + /* struct _objc_class *super_class; */ + add_field_decl (build_pointer_type (objc_class_template), + "super_class", &chain); + + objc_finish_struct (objc_super_template, decls); +} + +/* To accomplish method prototyping without generating all kinds of + inane warnings, the definition of the dispatch table entries were + changed from: + + struct objc_method { SEL _cmd; ...; id (*_imp)(); }; + to: + struct objc_method { SEL _cmd; ...; void *_imp; }; */ + +tree +build_method_template (void) +{ + tree _SLT_record; + tree decls, *chain = NULL; + + _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD)); + + /* SEL _cmd; */ + decls = add_field_decl (objc_selector_type, "_cmd", &chain); + + /* char *method_types; */ + add_field_decl (string_type_node, "method_types", &chain); + + /* void *_imp; */ + add_field_decl (build_pointer_type (void_type_node), "_imp", &chain); + + objc_finish_struct (_SLT_record, decls); + + return _SLT_record; +} + +tree +build_method_prototype_template (void) +{ + tree proto_record; + tree decls, *chain = NULL; + + proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE)); + + /* SEL _cmd; */ + decls = add_field_decl (objc_selector_type, "_cmd", &chain); + + /* char *method_types; */ + add_field_decl (string_type_node, "method_types", &chain); + + objc_finish_struct (proto_record, decls); + + return proto_record; +} + +/* struct { + struct _objc__method_prototype_list *method_next; + int method_count; + struct objc_method method_list[method_count]; + }; */ + +tree +build_method_list_template (tree list_type, int size) +{ + tree objc_ivar_list_record; + tree array_type, decls, *chain = NULL; + + objc_ivar_list_record = objc_start_struct (NULL_TREE); + + /* struct _objc__method_prototype_list *method_next; */ + decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain); + + /* int method_count; */ + add_field_decl (integer_type_node, "method_count", &chain); + + /* struct objc_method method_list[]; */ + array_type = build_sized_array_type (list_type, size); + add_field_decl (array_type, "method_list", &chain); + + objc_finish_struct (objc_ivar_list_record, decls); + + return objc_ivar_list_record; +} + +/* struct objc_method_prototype_list { + int count; + struct objc_method_prototype { + SEL name; + char *types; + } list[1]; + }; */ + +tree +build_method_prototype_list_template (tree list_type, int size) +{ + tree objc_ivar_list_record; + tree array_type, decls, *chain = NULL; + + /* Generate an unnamed struct definition. */ + + objc_ivar_list_record = objc_start_struct (NULL_TREE); + + /* int method_count; */ + decls = add_field_decl (integer_type_node, "method_count", &chain); + + /* struct objc_method method_list[]; */ + array_type = build_sized_array_type (list_type, size); + add_field_decl (array_type, "method_list", &chain); + + objc_finish_struct (objc_ivar_list_record, decls); + + return objc_ivar_list_record; +} + +/* --- names, decls entry --- */ + +/* For each string section we have a chain which maps identifier nodes + to decls for the strings. */ + +static GTY(()) int meth_var_names_idx; +static GTY(()) int meth_var_types_idx; +static GTY(()) int property_name_attr_idx; + +tree +add_objc_string (tree ident, string_section section) +{ + tree *chain, decl, type; + char buf[BUFSIZE]; + + switch (section) + { + case class_names: + chain = &class_names_chain; + snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident)); + break; + case meth_var_names: + chain = &meth_var_names_chain; + snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); + break; + case meth_var_types: + chain = &meth_var_types_chain; + snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); + break; + case prop_names_attr: + chain = &prop_names_attr_chain; + snprintf (buf, BUFSIZE, "_OBJC_PropertyAttributeOrName_%d", property_name_attr_idx++); + break; + default: + gcc_unreachable (); + } + + while (*chain) + { + if (TREE_VALUE (*chain) == ident) + return convert (string_type_node, + build_unary_op (input_location, + ADDR_EXPR, TREE_PURPOSE (*chain), 1)); + + chain = &TREE_CHAIN (*chain); + } + + type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1); + /* Get a runtime-specific string decl which will be finish_var()'ed in + generate_strings (). */ + decl = (*runtime.string_decl) (type, buf, section); + TREE_CONSTANT (decl) = 1; + *chain = tree_cons (decl, ident, NULL_TREE); + + return convert (string_type_node, + build_unary_op (input_location, ADDR_EXPR, decl, 1)); +} + +/* --- shared metadata routines --- */ + +tree +build_descriptor_table_initializer (tree type, tree entries) +{ + VEC(constructor_elt,gc) *inits = NULL; + + do + { + VEC(constructor_elt,gc) *elts = NULL; + + CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, + build_selector (METHOD_SEL_NAME (entries))); + CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, + add_objc_string (METHOD_ENCODING (entries), + meth_var_types)); + + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, + objc_build_constructor (type, elts)); + + entries = DECL_CHAIN (entries); + } + while (entries); + + return objc_build_constructor (build_array_type (type, 0), inits); +} + +tree +build_dispatch_table_initializer (tree type, tree entries) +{ + VEC(constructor_elt,gc) *inits = NULL; + + do + { + VEC(constructor_elt,gc) *elems = NULL; + tree expr; + + CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, + build_selector (METHOD_SEL_NAME (entries))); + + /* Generate the method encoding if we don't have one already. */ + if (! METHOD_ENCODING (entries)) + METHOD_ENCODING (entries) = + encode_method_prototype (entries); + + CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, + add_objc_string (METHOD_ENCODING (entries), + meth_var_types)); + + expr = convert (ptr_type_node, + build_unary_op (input_location, ADDR_EXPR, + METHOD_DEFINITION (entries), 1)); + CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr); + + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, + objc_build_constructor (type, elems)); + + entries = DECL_CHAIN (entries); + } + while (entries); + + return objc_build_constructor (build_array_type (type, 0), inits); +} + +/* Used only by build_*_selector_translation_table (). */ +void +diagnose_missing_method (tree meth, location_t here) +{ + tree method_chain; + bool found = false; + for (method_chain = meth_var_names_chain; + method_chain; + method_chain = TREE_CHAIN (method_chain)) + { + if (TREE_VALUE (method_chain) == meth) + { + found = true; + break; + } + } + + if (!found) + warning_at (here, 0, "creating selector for nonexistent method %qE", + meth); +} + + +static tree +init_module_descriptor (tree type, long vers) +{ + tree expr, ltyp; + location_t loc; + VEC(constructor_elt,gc) *v = NULL; + + /* No really useful place to point to. */ + loc = UNKNOWN_LOCATION; + + /* version = { 1, ... } */ + + expr = build_int_cst (long_integer_type_node, vers); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); + + /* size = { ..., sizeof (struct _objc_module), ... } */ + + expr = convert (long_integer_type_node, + size_in_bytes (objc_module_template)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); + + /* Don't provide any file name for security reasons. */ + /* name = { ..., "", ... } */ + + expr = add_objc_string (get_identifier (""), class_names); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); + + /* symtab = { ..., _OBJC_SYMBOLS, ... } */ + + ltyp = build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (UTAG_SYMTAB))); + if (UOBJC_SYMBOLS_decl) + expr = convert (ltyp, build_unary_op (loc, + ADDR_EXPR, UOBJC_SYMBOLS_decl, 0)); + else + expr = convert (ltyp, null_pointer_node); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); + + return objc_build_constructor (type, v); +} + +/* Write out the data structures to describe Objective C classes defined. + + struct _objc_module { ... } _OBJC_MODULE = { ... }; */ + +void +build_module_descriptor (long vers, tree attr) +{ + tree decls, *chain = NULL; + +#ifdef OBJCPLUS + push_lang_context (lang_name_c); /* extern "C" */ +#endif + + objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE)); + + /* long version; */ + decls = add_field_decl (long_integer_type_node, "version", &chain); + + /* long size; */ + add_field_decl (long_integer_type_node, "size", &chain); + + /* char *name; */ + add_field_decl (string_type_node, "name", &chain); + + /* struct _objc_symtab *symtab; */ + add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (UTAG_SYMTAB))), + "symtab", &chain); + + objc_finish_struct (objc_module_template, decls); + + /* Create an instance of "_objc_module". */ + UOBJC_MODULES_decl = start_var_decl (objc_module_template, + /* FIXME - why the conditional + if the symbol is the + same. */ + flag_next_runtime ? "_OBJC_Module" : "_OBJC_Module"); + + /* This is the root of the metadata for defined classes and categories, it + is referenced by the runtime and, therefore, needed. */ + DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1; + + /* Allow the runtime to mark meta-data such that it can be assigned to target + specific sections by the back-end. */ + if (attr) + DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr; + + finish_var_decl (UOBJC_MODULES_decl, + init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl), + vers)); + +#ifdef OBJCPLUS + pop_lang_context (); +#endif +} + +tree +build_ivar_list_initializer (tree type, tree field_decl) +{ + VEC(constructor_elt,gc) *inits = NULL; + + do + { + VEC(constructor_elt,gc) *ivar = NULL; + tree id; + + /* Set name. */ + if (DECL_NAME (field_decl)) + CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, + add_objc_string (DECL_NAME (field_decl), + meth_var_names)); + else + /* Unnamed bit-field ivar (yuck). */ + CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0)); + + /* Set type. */ + encode_field_decl (field_decl, + obstack_object_size (&util_obstack), + OBJC_ENCODE_DONT_INLINE_DEFS); + + /* Null terminate string. */ + obstack_1grow (&util_obstack, 0); + id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)), + meth_var_types); + CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id); + obstack_free (&util_obstack, util_firstobj); + + /* Set offset. */ + CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl)); + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, + objc_build_constructor (type, ivar)); + do + field_decl = DECL_CHAIN (field_decl); + while (field_decl && TREE_CODE (field_decl) != FIELD_DECL); + } + while (field_decl); + + return objc_build_constructor (build_array_type (type, 0), inits); +} + +/* struct { + int ivar_count; + struct objc_ivar ivar_list[ivar_count]; + }; */ + +tree +build_ivar_list_template (tree list_type, int size) +{ + tree objc_ivar_list_record; + tree array_type, decls, *chain = NULL; + + objc_ivar_list_record = objc_start_struct (NULL_TREE); + + /* int ivar_count; */ + decls = add_field_decl (integer_type_node, "ivar_count", &chain); + + /* struct objc_ivar ivar_list[]; */ + array_type = build_sized_array_type (list_type, size); + add_field_decl (array_type, "ivar_list", &chain); + + objc_finish_struct (objc_ivar_list_record, decls); + + return objc_ivar_list_record; +} + +/* struct _objc_ivar { + char *ivar_name; + char *ivar_type; + int ivar_offset; + }; */ + +tree +build_ivar_template (void) +{ + tree objc_ivar_id, objc_ivar_record; + tree decls, *chain = NULL; + + objc_ivar_id = get_identifier (UTAG_IVAR); + objc_ivar_record = objc_start_struct (objc_ivar_id); + + /* char *ivar_name; */ + decls = add_field_decl (string_type_node, "ivar_name", &chain); + + /* char *ivar_type; */ + add_field_decl (string_type_node, "ivar_type", &chain); + + /* int ivar_offset; */ + add_field_decl (integer_type_node, "ivar_offset", &chain); + + objc_finish_struct (objc_ivar_record, decls); + + return objc_ivar_record; +} + +/* Used by NeXT ABI=0..2 */ +void +build_next_selector_translation_table (void) +{ + tree chain; + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + { + tree expr; + tree decl = TREE_PURPOSE (chain); + if (warn_selector) + { + location_t loc; + if (decl) + loc = DECL_SOURCE_LOCATION (decl); + else + loc = UNKNOWN_LOCATION; + diagnose_missing_method (TREE_VALUE (chain), loc); + } + + expr = build_selector (TREE_VALUE (chain)); + + if (decl) + { + /* Entries of this form are used for references to methods. + The runtime re-writes these on start-up, but the compiler can't see + that and optimizes it away unless we force it. */ + DECL_PRESERVE_P (decl) = 1; + finish_var_decl (decl, expr); + } + } +} + +void +generate_protocol_references (tree plist) +{ + tree lproto; + + /* Forward declare protocols referenced. */ + for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) + { + tree proto = TREE_VALUE (lproto); + + if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE + && PROTOCOL_NAME (proto)) + { + if (! PROTOCOL_FORWARD_DECL (proto)) + PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto); + + if (PROTOCOL_LIST (proto)) + generate_protocol_references (PROTOCOL_LIST (proto)); + } + } +} + +/* --- new routines --- */ + +/* Output all strings. */ + +/* FIXME: don't use global vars for all this... */ + +/* This emits all the meta-data string tables (and finalizes each var + as it goes). */ +void +generate_strings (void) +{ + tree chain, string_expr; + tree string, decl; /* , type;*/ + + for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_var_decl (decl, string_expr); + } + + for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_var_decl (decl, string_expr); + } + + for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_var_decl (decl, string_expr); + } + + for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_var_decl (decl, string_expr); + } +} + +#include "gt-objc-objc-runtime-shared-support.h" -- cgit v1.2.3