1*e4b17023SJohn Marino /* Support routines shared by all runtimes.
2*e4b17023SJohn Marino    Copyright (C) 2011 Free Software Foundation, Inc.
3*e4b17023SJohn Marino    Contributed by Iain Sandoe (partially split from objc-act.c)
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
8*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino any later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino GNU General Public License for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #ifdef OBJCPLUS
28*e4b17023SJohn Marino #include "cp-tree.h"
29*e4b17023SJohn Marino #else
30*e4b17023SJohn Marino #include "c-tree.h"
31*e4b17023SJohn Marino #include "c-lang.h"
32*e4b17023SJohn Marino #endif
33*e4b17023SJohn Marino #include "langhooks.h"
34*e4b17023SJohn Marino #include "c-family/c-objc.h"
35*e4b17023SJohn Marino #include "objc-act.h"
36*e4b17023SJohn Marino 
37*e4b17023SJohn Marino /* When building Objective-C++, we are not linking against the C front-end
38*e4b17023SJohn Marino    and so need to replicate the C tree-construction functions in some way.  */
39*e4b17023SJohn Marino #ifdef OBJCPLUS
40*e4b17023SJohn Marino #define OBJCP_REMAP_FUNCTIONS
41*e4b17023SJohn Marino #include "objcp-decl.h"
42*e4b17023SJohn Marino #endif  /* OBJCPLUS */
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino /* Hooks for string decls etc.  */
45*e4b17023SJohn Marino #include "objc-runtime-hooks.h"
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino #include "objc-runtime-shared-support.h"
48*e4b17023SJohn Marino #include "objc-encoding.h"
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* rt_trees identifiers - shared between NeXT implementations.  These allow
51*e4b17023SJohn Marino    the FE to tag meta-data in a manner that survives LTO and can be used when
52*e4b17023SJohn Marino    the  runtime requires that certain meta-data items appear in particular
53*e4b17023SJohn Marino    named sections.  */
54*e4b17023SJohn Marino #include "objc-next-metadata-tags.h"
55*e4b17023SJohn Marino extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino /* Rather than repeatedly looking up the identifiers, we save them here.  */
58*e4b17023SJohn Marino tree objc_rt_trees[OCTI_RT_META_MAX];
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino /* For building an objc struct.  These might not be used when this file
61*e4b17023SJohn Marino    is compiled as part of obj-c++.  */
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino static bool objc_building_struct;
64*e4b17023SJohn Marino static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino /* Start building a struct for objc.  */
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino tree
objc_start_struct(tree name)69*e4b17023SJohn Marino objc_start_struct (tree name)
70*e4b17023SJohn Marino {
71*e4b17023SJohn Marino   gcc_assert (!objc_building_struct);
72*e4b17023SJohn Marino   objc_building_struct = true;
73*e4b17023SJohn Marino   return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
74*e4b17023SJohn Marino }
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino /* Finish building a struct for objc.  */
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino tree
objc_finish_struct(tree type,tree fieldlist)79*e4b17023SJohn Marino objc_finish_struct (tree type, tree fieldlist)
80*e4b17023SJohn Marino {
81*e4b17023SJohn Marino   gcc_assert (objc_building_struct);
82*e4b17023SJohn Marino   objc_building_struct = false;
83*e4b17023SJohn Marino   return finish_struct (input_location, type, fieldlist, NULL_TREE,
84*e4b17023SJohn Marino 			objc_struct_info);
85*e4b17023SJohn Marino }
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino tree
build_sized_array_type(tree base_type,int size)88*e4b17023SJohn Marino build_sized_array_type (tree base_type, int size)
89*e4b17023SJohn Marino {
90*e4b17023SJohn Marino   tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
91*e4b17023SJohn Marino   return build_array_type (base_type, index_type);
92*e4b17023SJohn Marino }
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino /* Create a declaration for field NAME of a given TYPE.  */
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino static tree
create_field_decl(tree type,const char * name)97*e4b17023SJohn Marino create_field_decl (tree type, const char *name)
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino   return build_decl (input_location,
100*e4b17023SJohn Marino 		     FIELD_DECL, get_identifier (name), type);
101*e4b17023SJohn Marino }
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino tree
add_field_decl(tree type,const char * name,tree ** chain)104*e4b17023SJohn Marino add_field_decl (tree type, const char *name, tree **chain)
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino   tree field = create_field_decl (type, name);
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino   if (*chain != NULL)
109*e4b17023SJohn Marino     **chain = field;
110*e4b17023SJohn Marino   *chain = &DECL_CHAIN (field);
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino   return field;
113*e4b17023SJohn Marino }
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino /* Create a global, static declaration for variable NAME of a given TYPE.  The
116*e4b17023SJohn Marino    finish_var_decl() routine will need to be called on it afterwards.  */
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino tree
start_var_decl(tree type,const char * name)119*e4b17023SJohn Marino start_var_decl (tree type, const char *name)
120*e4b17023SJohn Marino {
121*e4b17023SJohn Marino   tree var = build_decl (input_location,
122*e4b17023SJohn Marino 			 VAR_DECL, get_identifier (name), type);
123*e4b17023SJohn Marino   TREE_STATIC (var) = 1;
124*e4b17023SJohn Marino   DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
125*e4b17023SJohn Marino   DECL_IGNORED_P (var) = 1;
126*e4b17023SJohn Marino   DECL_ARTIFICIAL (var) = 1;
127*e4b17023SJohn Marino   DECL_CONTEXT (var) = NULL_TREE;
128*e4b17023SJohn Marino #ifdef OBJCPLUS
129*e4b17023SJohn Marino   DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
130*e4b17023SJohn Marino #endif
131*e4b17023SJohn Marino   return var;
132*e4b17023SJohn Marino }
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino /* Finish off the variable declaration created by start_var_decl().  */
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino void
finish_var_decl(tree var,tree initializer)137*e4b17023SJohn Marino finish_var_decl (tree var, tree initializer)
138*e4b17023SJohn Marino {
139*e4b17023SJohn Marino   finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
140*e4b17023SJohn Marino }
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino /* Just a handy wrapper for add_objc_string.  */
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino tree
build_selector(tree ident)145*e4b17023SJohn Marino build_selector (tree ident)
146*e4b17023SJohn Marino {
147*e4b17023SJohn Marino   return convert (objc_selector_type, add_objc_string (ident, meth_var_names));
148*e4b17023SJohn Marino }
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino /* --- templates --- */
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
153*e4b17023SJohn Marino    This needs to be done just once per compilation.  */
154*e4b17023SJohn Marino 
155*e4b17023SJohn Marino /* struct _objc_super {
156*e4b17023SJohn Marino      struct _objc_object *self;
157*e4b17023SJohn Marino      struct _objc_class *super_class;
158*e4b17023SJohn Marino 		[or Class cls; for the abi v2]
159*e4b17023SJohn Marino    };  */
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino void
build_super_template(void)162*e4b17023SJohn Marino build_super_template (void)
163*e4b17023SJohn Marino {
164*e4b17023SJohn Marino   tree decls, *chain = NULL;
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino   /* struct _objc_object *self; */
169*e4b17023SJohn Marino   decls = add_field_decl (objc_object_type, "self", &chain);
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino   /* struct _objc_class *super_class; */
172*e4b17023SJohn Marino   add_field_decl (build_pointer_type (objc_class_template),
173*e4b17023SJohn Marino 		  "super_class", &chain);
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino   objc_finish_struct (objc_super_template, decls);
176*e4b17023SJohn Marino }
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino /* To accomplish method prototyping without generating all kinds of
179*e4b17023SJohn Marino    inane warnings, the definition of the dispatch table entries were
180*e4b17023SJohn Marino    changed from:
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino 	struct objc_method { SEL _cmd; ...; id (*_imp)(); };
183*e4b17023SJohn Marino    to:
184*e4b17023SJohn Marino 	struct objc_method { SEL _cmd; ...; void *_imp; };  */
185*e4b17023SJohn Marino 
186*e4b17023SJohn Marino tree
build_method_template(void)187*e4b17023SJohn Marino build_method_template (void)
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino   tree _SLT_record;
190*e4b17023SJohn Marino   tree decls, *chain = NULL;
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino   _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
193*e4b17023SJohn Marino 
194*e4b17023SJohn Marino   /* SEL _cmd; */
195*e4b17023SJohn Marino   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino   /* char *method_types; */
198*e4b17023SJohn Marino   add_field_decl (string_type_node, "method_types", &chain);
199*e4b17023SJohn Marino 
200*e4b17023SJohn Marino   /* void *_imp; */
201*e4b17023SJohn Marino   add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino   objc_finish_struct (_SLT_record, decls);
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino   return _SLT_record;
206*e4b17023SJohn Marino }
207*e4b17023SJohn Marino 
208*e4b17023SJohn Marino tree
build_method_prototype_template(void)209*e4b17023SJohn Marino build_method_prototype_template (void)
210*e4b17023SJohn Marino {
211*e4b17023SJohn Marino   tree proto_record;
212*e4b17023SJohn Marino   tree decls, *chain = NULL;
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
215*e4b17023SJohn Marino 
216*e4b17023SJohn Marino   /* SEL _cmd; */
217*e4b17023SJohn Marino   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   /* char *method_types; */
220*e4b17023SJohn Marino   add_field_decl (string_type_node, "method_types", &chain);
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino   objc_finish_struct (proto_record, decls);
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino   return proto_record;
225*e4b17023SJohn Marino }
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino /* struct {
228*e4b17023SJohn Marino      struct _objc__method_prototype_list *method_next;
229*e4b17023SJohn Marino      int method_count;
230*e4b17023SJohn Marino      struct objc_method method_list[method_count];
231*e4b17023SJohn Marino    };  */
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino tree
build_method_list_template(tree list_type,int size)234*e4b17023SJohn Marino build_method_list_template (tree list_type, int size)
235*e4b17023SJohn Marino {
236*e4b17023SJohn Marino   tree objc_ivar_list_record;
237*e4b17023SJohn Marino   tree array_type, decls, *chain = NULL;
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   objc_ivar_list_record = objc_start_struct (NULL_TREE);
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino   /* struct _objc__method_prototype_list *method_next; */
242*e4b17023SJohn Marino   decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino   /* int method_count; */
245*e4b17023SJohn Marino   add_field_decl (integer_type_node, "method_count", &chain);
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino   /* struct objc_method method_list[]; */
248*e4b17023SJohn Marino   array_type = build_sized_array_type (list_type, size);
249*e4b17023SJohn Marino   add_field_decl (array_type, "method_list", &chain);
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino   objc_finish_struct (objc_ivar_list_record, decls);
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino   return objc_ivar_list_record;
254*e4b17023SJohn Marino }
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino /* struct objc_method_prototype_list {
257*e4b17023SJohn Marino      int count;
258*e4b17023SJohn Marino      struct objc_method_prototype {
259*e4b17023SJohn Marino 	SEL name;
260*e4b17023SJohn Marino 	char *types;
261*e4b17023SJohn Marino      } list[1];
262*e4b17023SJohn Marino    };  */
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino tree
build_method_prototype_list_template(tree list_type,int size)265*e4b17023SJohn Marino build_method_prototype_list_template (tree list_type, int size)
266*e4b17023SJohn Marino {
267*e4b17023SJohn Marino   tree objc_ivar_list_record;
268*e4b17023SJohn Marino   tree array_type, decls, *chain = NULL;
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino   /* Generate an unnamed struct definition.  */
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino   objc_ivar_list_record = objc_start_struct (NULL_TREE);
273*e4b17023SJohn Marino 
274*e4b17023SJohn Marino   /* int method_count; */
275*e4b17023SJohn Marino   decls = add_field_decl (integer_type_node, "method_count", &chain);
276*e4b17023SJohn Marino 
277*e4b17023SJohn Marino   /* struct objc_method method_list[]; */
278*e4b17023SJohn Marino   array_type = build_sized_array_type (list_type, size);
279*e4b17023SJohn Marino   add_field_decl (array_type, "method_list", &chain);
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino   objc_finish_struct (objc_ivar_list_record, decls);
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino   return objc_ivar_list_record;
284*e4b17023SJohn Marino }
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino /* --- names, decls entry --- */
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino /* For each string section we have a chain which maps identifier nodes
289*e4b17023SJohn Marino    to decls for the strings.  */
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino static GTY(()) int meth_var_names_idx;
292*e4b17023SJohn Marino static GTY(()) int meth_var_types_idx;
293*e4b17023SJohn Marino static GTY(()) int property_name_attr_idx;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino tree
add_objc_string(tree ident,string_section section)296*e4b17023SJohn Marino add_objc_string (tree ident, string_section section)
297*e4b17023SJohn Marino {
298*e4b17023SJohn Marino   tree *chain, decl, type;
299*e4b17023SJohn Marino   char buf[BUFSIZE];
300*e4b17023SJohn Marino 
301*e4b17023SJohn Marino   switch (section)
302*e4b17023SJohn Marino     {
303*e4b17023SJohn Marino     case class_names:
304*e4b17023SJohn Marino       chain = &class_names_chain;
305*e4b17023SJohn Marino       snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident));
306*e4b17023SJohn Marino       break;
307*e4b17023SJohn Marino     case meth_var_names:
308*e4b17023SJohn Marino       chain = &meth_var_names_chain;
309*e4b17023SJohn Marino       snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
310*e4b17023SJohn Marino       break;
311*e4b17023SJohn Marino     case meth_var_types:
312*e4b17023SJohn Marino       chain = &meth_var_types_chain;
313*e4b17023SJohn Marino       snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
314*e4b17023SJohn Marino       break;
315*e4b17023SJohn Marino     case prop_names_attr:
316*e4b17023SJohn Marino       chain = &prop_names_attr_chain;
317*e4b17023SJohn Marino       snprintf (buf, BUFSIZE, "_OBJC_PropertyAttributeOrName_%d", property_name_attr_idx++);
318*e4b17023SJohn Marino       break;
319*e4b17023SJohn Marino     default:
320*e4b17023SJohn Marino       gcc_unreachable ();
321*e4b17023SJohn Marino     }
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino   while (*chain)
324*e4b17023SJohn Marino     {
325*e4b17023SJohn Marino       if (TREE_VALUE (*chain) == ident)
326*e4b17023SJohn Marino 	return convert (string_type_node,
327*e4b17023SJohn Marino 			build_unary_op (input_location,
328*e4b17023SJohn Marino 					ADDR_EXPR, TREE_PURPOSE (*chain), 1));
329*e4b17023SJohn Marino 
330*e4b17023SJohn Marino       chain = &TREE_CHAIN (*chain);
331*e4b17023SJohn Marino     }
332*e4b17023SJohn Marino 
333*e4b17023SJohn Marino   type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
334*e4b17023SJohn Marino   /* Get a runtime-specific string decl which will be finish_var()'ed in
335*e4b17023SJohn Marino      generate_strings ().  */
336*e4b17023SJohn Marino   decl = (*runtime.string_decl) (type, buf, section);
337*e4b17023SJohn Marino   TREE_CONSTANT (decl) = 1;
338*e4b17023SJohn Marino   *chain = tree_cons (decl, ident, NULL_TREE);
339*e4b17023SJohn Marino 
340*e4b17023SJohn Marino   return convert (string_type_node,
341*e4b17023SJohn Marino 		  build_unary_op (input_location, ADDR_EXPR, decl, 1));
342*e4b17023SJohn Marino }
343*e4b17023SJohn Marino 
344*e4b17023SJohn Marino /* --- shared metadata routines --- */
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino tree
build_descriptor_table_initializer(tree type,tree entries)347*e4b17023SJohn Marino build_descriptor_table_initializer (tree type, tree entries)
348*e4b17023SJohn Marino {
349*e4b17023SJohn Marino   VEC(constructor_elt,gc) *inits = NULL;
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino   do
352*e4b17023SJohn Marino     {
353*e4b17023SJohn Marino       VEC(constructor_elt,gc) *elts = NULL;
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
356*e4b17023SJohn Marino 			      build_selector (METHOD_SEL_NAME (entries)));
357*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
358*e4b17023SJohn Marino 			      add_objc_string (METHOD_ENCODING (entries),
359*e4b17023SJohn Marino 					       meth_var_types));
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
362*e4b17023SJohn Marino 			      objc_build_constructor (type, elts));
363*e4b17023SJohn Marino 
364*e4b17023SJohn Marino       entries = DECL_CHAIN (entries);
365*e4b17023SJohn Marino     }
366*e4b17023SJohn Marino   while (entries);
367*e4b17023SJohn Marino 
368*e4b17023SJohn Marino   return objc_build_constructor (build_array_type (type, 0), inits);
369*e4b17023SJohn Marino }
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino tree
build_dispatch_table_initializer(tree type,tree entries)372*e4b17023SJohn Marino build_dispatch_table_initializer (tree type, tree entries)
373*e4b17023SJohn Marino {
374*e4b17023SJohn Marino   VEC(constructor_elt,gc) *inits = NULL;
375*e4b17023SJohn Marino 
376*e4b17023SJohn Marino   do
377*e4b17023SJohn Marino     {
378*e4b17023SJohn Marino       VEC(constructor_elt,gc) *elems = NULL;
379*e4b17023SJohn Marino       tree expr;
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
382*e4b17023SJohn Marino 			      build_selector (METHOD_SEL_NAME (entries)));
383*e4b17023SJohn Marino 
384*e4b17023SJohn Marino       /* Generate the method encoding if we don't have one already.  */
385*e4b17023SJohn Marino       if (! METHOD_ENCODING (entries))
386*e4b17023SJohn Marino 	METHOD_ENCODING (entries) =
387*e4b17023SJohn Marino 	  encode_method_prototype (entries);
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
390*e4b17023SJohn Marino 			      add_objc_string (METHOD_ENCODING (entries),
391*e4b17023SJohn Marino 					       meth_var_types));
392*e4b17023SJohn Marino 
393*e4b17023SJohn Marino       expr = convert (ptr_type_node,
394*e4b17023SJohn Marino 		      build_unary_op (input_location, ADDR_EXPR,
395*e4b17023SJohn Marino 				      METHOD_DEFINITION (entries), 1));
396*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
399*e4b17023SJohn Marino 			      objc_build_constructor (type, elems));
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino       entries = DECL_CHAIN (entries);
402*e4b17023SJohn Marino     }
403*e4b17023SJohn Marino   while (entries);
404*e4b17023SJohn Marino 
405*e4b17023SJohn Marino   return objc_build_constructor (build_array_type (type, 0), inits);
406*e4b17023SJohn Marino }
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino /* Used only by build_*_selector_translation_table (). */
409*e4b17023SJohn Marino void
diagnose_missing_method(tree meth,location_t here)410*e4b17023SJohn Marino diagnose_missing_method (tree meth, location_t here)
411*e4b17023SJohn Marino {
412*e4b17023SJohn Marino   tree method_chain;
413*e4b17023SJohn Marino   bool found = false;
414*e4b17023SJohn Marino   for (method_chain = meth_var_names_chain;
415*e4b17023SJohn Marino        method_chain;
416*e4b17023SJohn Marino        method_chain = TREE_CHAIN (method_chain))
417*e4b17023SJohn Marino     {
418*e4b17023SJohn Marino       if (TREE_VALUE (method_chain) == meth)
419*e4b17023SJohn Marino 	{
420*e4b17023SJohn Marino 	  found = true;
421*e4b17023SJohn Marino 	  break;
422*e4b17023SJohn Marino 	}
423*e4b17023SJohn Marino      }
424*e4b17023SJohn Marino 
425*e4b17023SJohn Marino   if (!found)
426*e4b17023SJohn Marino     warning_at (here, 0, "creating selector for nonexistent method %qE",
427*e4b17023SJohn Marino 			meth);
428*e4b17023SJohn Marino }
429*e4b17023SJohn Marino 
430*e4b17023SJohn Marino 
431*e4b17023SJohn Marino static tree
init_module_descriptor(tree type,long vers)432*e4b17023SJohn Marino init_module_descriptor (tree type, long vers)
433*e4b17023SJohn Marino {
434*e4b17023SJohn Marino   tree expr, ltyp;
435*e4b17023SJohn Marino   location_t loc;
436*e4b17023SJohn Marino   VEC(constructor_elt,gc) *v = NULL;
437*e4b17023SJohn Marino 
438*e4b17023SJohn Marino   /* No really useful place to point to.  */
439*e4b17023SJohn Marino   loc = UNKNOWN_LOCATION;
440*e4b17023SJohn Marino 
441*e4b17023SJohn Marino   /* version = { 1, ... } */
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino   expr = build_int_cst (long_integer_type_node, vers);
444*e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino   /* size = { ..., sizeof (struct _objc_module), ... } */
447*e4b17023SJohn Marino 
448*e4b17023SJohn Marino   expr = convert (long_integer_type_node,
449*e4b17023SJohn Marino 		  size_in_bytes (objc_module_template));
450*e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
451*e4b17023SJohn Marino 
452*e4b17023SJohn Marino   /* Don't provide any file name for security reasons. */
453*e4b17023SJohn Marino   /* name = { ..., "", ... } */
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino   expr = add_objc_string (get_identifier (""), class_names);
456*e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
459*e4b17023SJohn Marino 
460*e4b17023SJohn Marino   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
461*e4b17023SJohn Marino 				       get_identifier (UTAG_SYMTAB)));
462*e4b17023SJohn Marino   if (UOBJC_SYMBOLS_decl)
463*e4b17023SJohn Marino     expr = convert (ltyp, build_unary_op (loc,
464*e4b17023SJohn Marino 			   ADDR_EXPR, UOBJC_SYMBOLS_decl, 0));
465*e4b17023SJohn Marino   else
466*e4b17023SJohn Marino     expr = convert (ltyp, null_pointer_node);
467*e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino   return objc_build_constructor (type, v);
470*e4b17023SJohn Marino }
471*e4b17023SJohn Marino 
472*e4b17023SJohn Marino /* Write out the data structures to describe Objective C classes defined.
473*e4b17023SJohn Marino 
474*e4b17023SJohn Marino    struct _objc_module { ... } _OBJC_MODULE = { ... };   */
475*e4b17023SJohn Marino 
476*e4b17023SJohn Marino void
build_module_descriptor(long vers,tree attr)477*e4b17023SJohn Marino build_module_descriptor (long vers, tree attr)
478*e4b17023SJohn Marino {
479*e4b17023SJohn Marino   tree decls, *chain = NULL;
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino #ifdef OBJCPLUS
482*e4b17023SJohn Marino   push_lang_context (lang_name_c); /* extern "C" */
483*e4b17023SJohn Marino #endif
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino   objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino   /* long version; */
488*e4b17023SJohn Marino   decls = add_field_decl (long_integer_type_node, "version", &chain);
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino   /* long size; */
491*e4b17023SJohn Marino   add_field_decl (long_integer_type_node, "size", &chain);
492*e4b17023SJohn Marino 
493*e4b17023SJohn Marino   /* char *name; */
494*e4b17023SJohn Marino   add_field_decl (string_type_node, "name", &chain);
495*e4b17023SJohn Marino 
496*e4b17023SJohn Marino   /* struct _objc_symtab *symtab; */
497*e4b17023SJohn Marino   add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
498*e4b17023SJohn Marino 						get_identifier (UTAG_SYMTAB))),
499*e4b17023SJohn Marino 		  "symtab", &chain);
500*e4b17023SJohn Marino 
501*e4b17023SJohn Marino   objc_finish_struct (objc_module_template, decls);
502*e4b17023SJohn Marino 
503*e4b17023SJohn Marino   /* Create an instance of "_objc_module".  */
504*e4b17023SJohn Marino   UOBJC_MODULES_decl = start_var_decl (objc_module_template,
505*e4b17023SJohn Marino 				       /* FIXME - why the conditional
506*e4b17023SJohn Marino 					  if the symbol is the
507*e4b17023SJohn Marino 					  same.  */
508*e4b17023SJohn Marino 				       flag_next_runtime ? "_OBJC_Module" :  "_OBJC_Module");
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino   /* This is the root of the metadata for defined classes and categories, it
511*e4b17023SJohn Marino      is referenced by the runtime and, therefore, needed.  */
512*e4b17023SJohn Marino   DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino   /* Allow the runtime to mark meta-data such that it can be assigned to target
515*e4b17023SJohn Marino      specific sections by the back-end.  */
516*e4b17023SJohn Marino   if (attr)
517*e4b17023SJohn Marino     DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr;
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino   finish_var_decl (UOBJC_MODULES_decl,
520*e4b17023SJohn Marino 		   init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
521*e4b17023SJohn Marino 					   vers));
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino #ifdef OBJCPLUS
524*e4b17023SJohn Marino   pop_lang_context ();
525*e4b17023SJohn Marino #endif
526*e4b17023SJohn Marino }
527*e4b17023SJohn Marino 
528*e4b17023SJohn Marino tree
build_ivar_list_initializer(tree type,tree field_decl)529*e4b17023SJohn Marino build_ivar_list_initializer (tree type, tree field_decl)
530*e4b17023SJohn Marino {
531*e4b17023SJohn Marino   VEC(constructor_elt,gc) *inits = NULL;
532*e4b17023SJohn Marino 
533*e4b17023SJohn Marino   do
534*e4b17023SJohn Marino     {
535*e4b17023SJohn Marino       VEC(constructor_elt,gc) *ivar = NULL;
536*e4b17023SJohn Marino       tree id;
537*e4b17023SJohn Marino 
538*e4b17023SJohn Marino       /* Set name.  */
539*e4b17023SJohn Marino       if (DECL_NAME (field_decl))
540*e4b17023SJohn Marino 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
541*e4b17023SJohn Marino 				add_objc_string (DECL_NAME (field_decl),
542*e4b17023SJohn Marino 						 meth_var_names));
543*e4b17023SJohn Marino       else
544*e4b17023SJohn Marino 	/* Unnamed bit-field ivar (yuck).  */
545*e4b17023SJohn Marino 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino       /* Set type.  */
548*e4b17023SJohn Marino       id = add_objc_string (encode_field_decl (field_decl),
549*e4b17023SJohn Marino                             meth_var_types);
550*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
551*e4b17023SJohn Marino 
552*e4b17023SJohn Marino       /* Set offset.  */
553*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
554*e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
555*e4b17023SJohn Marino 			      objc_build_constructor (type, ivar));
556*e4b17023SJohn Marino       do
557*e4b17023SJohn Marino 	field_decl = DECL_CHAIN (field_decl);
558*e4b17023SJohn Marino       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
559*e4b17023SJohn Marino     }
560*e4b17023SJohn Marino   while (field_decl);
561*e4b17023SJohn Marino 
562*e4b17023SJohn Marino   return objc_build_constructor (build_array_type (type, 0), inits);
563*e4b17023SJohn Marino }
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino /* struct {
566*e4b17023SJohn Marino      int ivar_count;
567*e4b17023SJohn Marino      struct objc_ivar ivar_list[ivar_count];
568*e4b17023SJohn Marino    };  */
569*e4b17023SJohn Marino 
570*e4b17023SJohn Marino tree
build_ivar_list_template(tree list_type,int size)571*e4b17023SJohn Marino build_ivar_list_template (tree list_type, int size)
572*e4b17023SJohn Marino {
573*e4b17023SJohn Marino   tree objc_ivar_list_record;
574*e4b17023SJohn Marino   tree array_type, decls, *chain = NULL;
575*e4b17023SJohn Marino 
576*e4b17023SJohn Marino   objc_ivar_list_record = objc_start_struct (NULL_TREE);
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino   /* int ivar_count; */
579*e4b17023SJohn Marino   decls = add_field_decl (integer_type_node, "ivar_count", &chain);
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino   /* struct objc_ivar ivar_list[]; */
582*e4b17023SJohn Marino   array_type = build_sized_array_type (list_type, size);
583*e4b17023SJohn Marino   add_field_decl (array_type, "ivar_list", &chain);
584*e4b17023SJohn Marino 
585*e4b17023SJohn Marino   objc_finish_struct (objc_ivar_list_record, decls);
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino   return objc_ivar_list_record;
588*e4b17023SJohn Marino }
589*e4b17023SJohn Marino 
590*e4b17023SJohn Marino /* struct _objc_ivar {
591*e4b17023SJohn Marino      char *ivar_name;
592*e4b17023SJohn Marino      char *ivar_type;
593*e4b17023SJohn Marino      int ivar_offset;
594*e4b17023SJohn Marino    };  */
595*e4b17023SJohn Marino 
596*e4b17023SJohn Marino tree
build_ivar_template(void)597*e4b17023SJohn Marino build_ivar_template (void)
598*e4b17023SJohn Marino {
599*e4b17023SJohn Marino   tree objc_ivar_id, objc_ivar_record;
600*e4b17023SJohn Marino   tree decls, *chain = NULL;
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino   objc_ivar_id = get_identifier (UTAG_IVAR);
603*e4b17023SJohn Marino   objc_ivar_record = objc_start_struct (objc_ivar_id);
604*e4b17023SJohn Marino 
605*e4b17023SJohn Marino   /* char *ivar_name; */
606*e4b17023SJohn Marino   decls = add_field_decl (string_type_node, "ivar_name", &chain);
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino   /* char *ivar_type; */
609*e4b17023SJohn Marino   add_field_decl (string_type_node, "ivar_type", &chain);
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino   /* int ivar_offset; */
612*e4b17023SJohn Marino   add_field_decl (integer_type_node, "ivar_offset", &chain);
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino   objc_finish_struct (objc_ivar_record, decls);
615*e4b17023SJohn Marino 
616*e4b17023SJohn Marino   return objc_ivar_record;
617*e4b17023SJohn Marino }
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino /* Used by NeXT ABI=0..2 */
620*e4b17023SJohn Marino void
build_next_selector_translation_table(void)621*e4b17023SJohn Marino build_next_selector_translation_table (void)
622*e4b17023SJohn Marino {
623*e4b17023SJohn Marino   tree chain;
624*e4b17023SJohn Marino   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
625*e4b17023SJohn Marino     {
626*e4b17023SJohn Marino       tree expr;
627*e4b17023SJohn Marino       tree decl = TREE_PURPOSE (chain);
628*e4b17023SJohn Marino       if (warn_selector)
629*e4b17023SJohn Marino 	{
630*e4b17023SJohn Marino 	  location_t loc;
631*e4b17023SJohn Marino 	  if (decl)
632*e4b17023SJohn Marino 	    loc = DECL_SOURCE_LOCATION (decl);
633*e4b17023SJohn Marino 	  else
634*e4b17023SJohn Marino 	    loc = UNKNOWN_LOCATION;
635*e4b17023SJohn Marino 	  diagnose_missing_method (TREE_VALUE (chain), loc);
636*e4b17023SJohn Marino 	}
637*e4b17023SJohn Marino 
638*e4b17023SJohn Marino       expr = build_selector (TREE_VALUE (chain));
639*e4b17023SJohn Marino 
640*e4b17023SJohn Marino       if (decl)
641*e4b17023SJohn Marino 	{
642*e4b17023SJohn Marino 	  /* Entries of this form are used for references to methods.
643*e4b17023SJohn Marino 	  The runtime re-writes these on start-up, but the compiler can't see
644*e4b17023SJohn Marino 	  that and optimizes it away unless we force it.  */
645*e4b17023SJohn Marino 	  DECL_PRESERVE_P (decl) = 1;
646*e4b17023SJohn Marino 	  finish_var_decl (decl, expr);
647*e4b17023SJohn Marino 	}
648*e4b17023SJohn Marino     }
649*e4b17023SJohn Marino }
650*e4b17023SJohn Marino 
651*e4b17023SJohn Marino void
generate_protocol_references(tree plist)652*e4b17023SJohn Marino generate_protocol_references (tree plist)
653*e4b17023SJohn Marino {
654*e4b17023SJohn Marino   tree lproto;
655*e4b17023SJohn Marino 
656*e4b17023SJohn Marino   /* Forward declare protocols referenced.  */
657*e4b17023SJohn Marino   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
658*e4b17023SJohn Marino     {
659*e4b17023SJohn Marino       tree proto = TREE_VALUE (lproto);
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
662*e4b17023SJohn Marino 	  && PROTOCOL_NAME (proto))
663*e4b17023SJohn Marino 	{
664*e4b17023SJohn Marino           if (! PROTOCOL_FORWARD_DECL (proto))
665*e4b17023SJohn Marino             PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
666*e4b17023SJohn Marino 
667*e4b17023SJohn Marino           if (PROTOCOL_LIST (proto))
668*e4b17023SJohn Marino             generate_protocol_references (PROTOCOL_LIST (proto));
669*e4b17023SJohn Marino         }
670*e4b17023SJohn Marino     }
671*e4b17023SJohn Marino }
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino /* --- new routines --- */
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino /* Output all strings.  */
676*e4b17023SJohn Marino 
677*e4b17023SJohn Marino /* FIXME: don't use global vars for all this... */
678*e4b17023SJohn Marino 
679*e4b17023SJohn Marino /* This emits all the meta-data string tables (and finalizes each var
680*e4b17023SJohn Marino    as it goes).  */
681*e4b17023SJohn Marino void
generate_strings(void)682*e4b17023SJohn Marino generate_strings (void)
683*e4b17023SJohn Marino {
684*e4b17023SJohn Marino   tree chain, string_expr;
685*e4b17023SJohn Marino   tree string, decl; /* , type;*/
686*e4b17023SJohn Marino 
687*e4b17023SJohn Marino   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
688*e4b17023SJohn Marino     {
689*e4b17023SJohn Marino       string = TREE_VALUE (chain);
690*e4b17023SJohn Marino       decl = TREE_PURPOSE (chain);
691*e4b17023SJohn Marino       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
692*e4b17023SJohn Marino 				     IDENTIFIER_POINTER (string));
693*e4b17023SJohn Marino       finish_var_decl (decl, string_expr);
694*e4b17023SJohn Marino     }
695*e4b17023SJohn Marino 
696*e4b17023SJohn Marino   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
697*e4b17023SJohn Marino     {
698*e4b17023SJohn Marino       string = TREE_VALUE (chain);
699*e4b17023SJohn Marino       decl = TREE_PURPOSE (chain);
700*e4b17023SJohn Marino       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
701*e4b17023SJohn Marino 				     IDENTIFIER_POINTER (string));
702*e4b17023SJohn Marino       finish_var_decl (decl, string_expr);
703*e4b17023SJohn Marino     }
704*e4b17023SJohn Marino 
705*e4b17023SJohn Marino   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
706*e4b17023SJohn Marino     {
707*e4b17023SJohn Marino       string = TREE_VALUE (chain);
708*e4b17023SJohn Marino       decl = TREE_PURPOSE (chain);
709*e4b17023SJohn Marino       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
710*e4b17023SJohn Marino 				     IDENTIFIER_POINTER (string));
711*e4b17023SJohn Marino       finish_var_decl (decl, string_expr);
712*e4b17023SJohn Marino     }
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino   for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
715*e4b17023SJohn Marino     {
716*e4b17023SJohn Marino       string = TREE_VALUE (chain);
717*e4b17023SJohn Marino       decl = TREE_PURPOSE (chain);
718*e4b17023SJohn Marino       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
719*e4b17023SJohn Marino 				     IDENTIFIER_POINTER (string));
720*e4b17023SJohn Marino       finish_var_decl (decl, string_expr);
721*e4b17023SJohn Marino     }
722*e4b17023SJohn Marino }
723*e4b17023SJohn Marino 
724*e4b17023SJohn Marino #include "gt-objc-objc-runtime-shared-support.h"
725