annotate gcc/objc/objc-next-runtime-abi-01.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Next Runtime (ABI-0/1) private.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Iain Sandoe (split from objc-act.c)
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
15 GNU General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 /* This implements the original NeXT ABI (0) used for m32 code and
kono
parents:
diff changeset
22 indicated by module version 6. It also implements the small number
kono
parents:
diff changeset
23 of additions made for properties and optional protocol methods as
kono
parents:
diff changeset
24 ABI=1 (module version 7). */
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 #include "config.h"
kono
parents:
diff changeset
27 #include "system.h"
kono
parents:
diff changeset
28 #include "coretypes.h"
kono
parents:
diff changeset
29 #include "tree.h"
kono
parents:
diff changeset
30 #include "stringpool.h"
kono
parents:
diff changeset
31 #include "attribs.h"
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 #ifdef OBJCPLUS
kono
parents:
diff changeset
34 #include "cp/cp-tree.h"
kono
parents:
diff changeset
35 #else
kono
parents:
diff changeset
36 #include "c/c-tree.h"
kono
parents:
diff changeset
37 #include "c/c-lang.h"
kono
parents:
diff changeset
38 #endif
kono
parents:
diff changeset
39 #include "langhooks.h"
kono
parents:
diff changeset
40 #include "c-family/c-objc.h"
kono
parents:
diff changeset
41 #include "objc-act.h"
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 /* When building Objective-C++, we are not linking against the C
kono
parents:
diff changeset
44 front-end and so need to replicate the C tree-construction
kono
parents:
diff changeset
45 functions in some way. */
kono
parents:
diff changeset
46 #ifdef OBJCPLUS
kono
parents:
diff changeset
47 #define OBJCP_REMAP_FUNCTIONS
kono
parents:
diff changeset
48 #include "objcp-decl.h"
kono
parents:
diff changeset
49 #endif /* OBJCPLUS */
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 #include "target.h"
kono
parents:
diff changeset
52 #include "c-family/c-target.h"
kono
parents:
diff changeset
53 #include "tree-iterator.h"
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 #include "objc-runtime-hooks.h"
kono
parents:
diff changeset
56 #include "objc-runtime-shared-support.h"
kono
parents:
diff changeset
57 #include "objc-encoding.h"
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 /* NeXT ABI 0 and 1 private definitions. */
kono
parents:
diff changeset
60 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 #define TAG_GETCLASS "objc_getClass"
kono
parents:
diff changeset
63 #define TAG_GETMETACLASS "objc_getMetaClass"
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 #define TAG_MSGSEND "objc_msgSend"
kono
parents:
diff changeset
66 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
kono
parents:
diff changeset
67 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
kono
parents:
diff changeset
68 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 /* NeXT-specific tags. */
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
kono
parents:
diff changeset
73 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
kono
parents:
diff changeset
74 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
kono
parents:
diff changeset
75 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
kono
parents:
diff changeset
76 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
kono
parents:
diff changeset
77 #define TAG_EXCEPTIONMATCH "objc_exception_match"
kono
parents:
diff changeset
78 #define TAG_SETJMP "_setjmp"
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 #define TAG_ASSIGNIVAR "objc_assign_ivar"
kono
parents:
diff changeset
81 #define TAG_ASSIGNGLOBAL "objc_assign_global"
kono
parents:
diff changeset
82 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 /* Branch entry points. All that matters here are the addresses;
kono
parents:
diff changeset
85 functions with these names do not really exist in libobjc. */
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 #define TAG_MSGSEND_FAST "objc_msgSend_Fast"
kono
parents:
diff changeset
88 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 /* The version identifies which language generation and runtime the
kono
parents:
diff changeset
91 module (file) was compiled for, and is recorded in the module
kono
parents:
diff changeset
92 descriptor. */
kono
parents:
diff changeset
93 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 #define UTAG_CLASS_EXT "_objc_class_ext"
kono
parents:
diff changeset
96 #define UTAG_PROPERTY_LIST "_prop_list_t"
kono
parents:
diff changeset
97 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 #define CLS_HAS_CXX_STRUCTORS 0x2000L
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 /* rt_trees identifiers - shared between NeXT implementations. These
kono
parents:
diff changeset
102 allow the FE to tag meta-data in a manner that survives LTO and can
kono
parents:
diff changeset
103 be used when the runtime requires that certain meta-data items
kono
parents:
diff changeset
104 appear in particular named sections. */
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 #include "objc-next-metadata-tags.h"
kono
parents:
diff changeset
107 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 static void next_runtime_01_initialize (void);
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 static tree next_runtime_abi_01_super_superclassfield_id (void);
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 static tree next_runtime_abi_01_class_decl (tree);
kono
parents:
diff changeset
114 static tree next_runtime_abi_01_metaclass_decl (tree);
kono
parents:
diff changeset
115 static tree next_runtime_abi_01_category_decl (tree);
kono
parents:
diff changeset
116 static tree next_runtime_abi_01_protocol_decl (tree);
kono
parents:
diff changeset
117 static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 static tree next_runtime_abi_01_get_class_reference (tree);
kono
parents:
diff changeset
120 static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
kono
parents:
diff changeset
121 static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
kono
parents:
diff changeset
122 static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
kono
parents:
diff changeset
123 static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
kono
parents:
diff changeset
124 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 static tree next_runtime_abi_01_receiver_is_class_object (tree);
kono
parents:
diff changeset
127 static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
kono
parents:
diff changeset
128 tree, int, int);
kono
parents:
diff changeset
129 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
kono
parents:
diff changeset
130 tree, tree, tree, int);
kono
parents:
diff changeset
131 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
kono
parents:
diff changeset
132 static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 static void objc_generate_v1_next_metadata (void);
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 static void build_next_objc_exception_stuff (void);
kono
parents:
diff changeset
137 static tree objc_eh_runtime_type (tree type);
kono
parents:
diff changeset
138 static tree objc_eh_personality (void);
kono
parents:
diff changeset
139 static tree build_throw_stmt (location_t, tree, bool);
kono
parents:
diff changeset
140 static tree objc_build_exc_ptr (struct objc_try_context **);
kono
parents:
diff changeset
141 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
kono
parents:
diff changeset
142 static void finish_catch (struct objc_try_context **, tree);
kono
parents:
diff changeset
143 static tree finish_try_stmt (struct objc_try_context **);
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 bool
kono
parents:
diff changeset
146 objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
kono
parents:
diff changeset
147 {
kono
parents:
diff changeset
148 if (flag_objc_exceptions
kono
parents:
diff changeset
149 && !flag_objc_sjlj_exceptions)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 warning_at (UNKNOWN_LOCATION, OPT_Wall,
kono
parents:
diff changeset
152 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
154 "argument less than 2");
111
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 rthooks->initialize = next_runtime_01_initialize;
kono
parents:
diff changeset
158 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
kono
parents:
diff changeset
159 rthooks->tag_getclass = TAG_GETCLASS;
kono
parents:
diff changeset
160 rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 rthooks->class_decl = next_runtime_abi_01_class_decl;
kono
parents:
diff changeset
163 rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
kono
parents:
diff changeset
164 rthooks->category_decl = next_runtime_abi_01_category_decl;
kono
parents:
diff changeset
165 rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
kono
parents:
diff changeset
166 rthooks->string_decl = next_runtime_abi_01_string_decl;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
kono
parents:
diff changeset
169 rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
kono
parents:
diff changeset
170 rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
kono
parents:
diff changeset
171 rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
kono
parents:
diff changeset
172 rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
kono
parents:
diff changeset
173 rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
kono
parents:
diff changeset
176 rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
kono
parents:
diff changeset
177 rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 rthooks->setup_const_string_class_decl =
kono
parents:
diff changeset
180 next_runtime_abi_01_setup_const_string_class_decl;
kono
parents:
diff changeset
181 rthooks->build_const_string_constructor =
kono
parents:
diff changeset
182 next_runtime_abi_01_build_const_string_constructor;
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 rthooks->build_throw_stmt = build_throw_stmt;
kono
parents:
diff changeset
185 rthooks->build_exc_ptr = objc_build_exc_ptr;
kono
parents:
diff changeset
186 rthooks->begin_catch = begin_catch;
kono
parents:
diff changeset
187 rthooks->finish_catch = finish_catch;
kono
parents:
diff changeset
188 rthooks->finish_try_stmt = finish_try_stmt;
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 rthooks->generate_metadata = objc_generate_v1_next_metadata;
kono
parents:
diff changeset
191 return true;
kono
parents:
diff changeset
192 }
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 /* We need a way to convey what kind of meta-data are represented by a
kono
parents:
diff changeset
195 given variable, since each type is expected (by the runtime) to be
kono
parents:
diff changeset
196 found in a specific named section. The solution must be usable
kono
parents:
diff changeset
197 with LTO.
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 The scheme used for NeXT ABI 0/1 (partial matching of variable
kono
parents:
diff changeset
200 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
kono
parents:
diff changeset
201 meta-data with identification attributes in the front end. The
kono
parents:
diff changeset
202 back-end may choose to act on these as it requires. */
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 static void
kono
parents:
diff changeset
205 next_runtime_abi_01_init_metadata_attributes (void)
kono
parents:
diff changeset
206 {
kono
parents:
diff changeset
207 if (!objc_meta)
kono
parents:
diff changeset
208 objc_meta = get_identifier ("OBJC1META");
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 if (!meta_base)
kono
parents:
diff changeset
211 meta_base = get_identifier ("V1_BASE");
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 meta_class = get_identifier ("V1_CLAS");
kono
parents:
diff changeset
214 meta_metaclass = get_identifier ("V1_META");
kono
parents:
diff changeset
215 meta_category = get_identifier ("V1_CATG");
kono
parents:
diff changeset
216 meta_protocol = get_identifier ("V1_PROT");
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 meta_clac_vars = get_identifier ("V1_CLCV");
kono
parents:
diff changeset
219 meta_clai_vars = get_identifier ("V1_CLIV");
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 meta_clac_meth = get_identifier ("V1_CLCM");
kono
parents:
diff changeset
222 meta_clai_meth = get_identifier ("V1_CLIM");
kono
parents:
diff changeset
223 meta_catc_meth = get_identifier ("V1_CACM");
kono
parents:
diff changeset
224 meta_cati_meth = get_identifier ("V1_CAIM");
kono
parents:
diff changeset
225 meta_proto_cls_meth = get_identifier ("V1_PCLM");
kono
parents:
diff changeset
226 meta_proto_nst_meth = get_identifier ("V1_PNSM");
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 meta_clas_prot = get_identifier ("V1_CLPR");
kono
parents:
diff changeset
229 meta_catg_prot = get_identifier ("V1_CAPR");
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 meta_class_reference = get_identifier ("V1_CLRF");
kono
parents:
diff changeset
232 meta_proto_ref = get_identifier ("V1_PRFS");
kono
parents:
diff changeset
233 meta_sel_refs = get_identifier ("V1_SRFS");
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 meta_class_name = get_identifier ("V1_CLSN");
kono
parents:
diff changeset
236 meta_meth_name = get_identifier ("V1_METN");
kono
parents:
diff changeset
237 meta_meth_type = get_identifier ("V1_METT");
kono
parents:
diff changeset
238 meta_prop_name_attr = get_identifier ("V1_STRG");
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 meta_modules = get_identifier ("V1_MODU");
kono
parents:
diff changeset
241 meta_symtab = get_identifier ("V1_SYMT");
kono
parents:
diff changeset
242 meta_info = get_identifier ("V1_INFO");
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 meta_proplist = get_identifier ("V1_PLST");
kono
parents:
diff changeset
245 meta_protocol_extension = get_identifier ("V1_PEXT");
kono
parents:
diff changeset
246 meta_class_extension = get_identifier ("V1_CEXT");
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 meta_const_str = get_identifier ("V1_CSTR");
kono
parents:
diff changeset
249 }
kono
parents:
diff changeset
250
kono
parents:
diff changeset
251 static void build_v1_class_template (void);
kono
parents:
diff changeset
252 static void build_v1_category_template (void);
kono
parents:
diff changeset
253 static void build_v1_protocol_template (void);
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 static void next_runtime_01_initialize (void)
kono
parents:
diff changeset
256 {
kono
parents:
diff changeset
257 tree type;
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 #ifdef OBJCPLUS
kono
parents:
diff changeset
260 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
kono
parents:
diff changeset
261 default. */
kono
parents:
diff changeset
262 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
kono
parents:
diff changeset
263 global_options.x_flag_objc_call_cxx_cdtors = 1;
kono
parents:
diff changeset
264 #endif
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 /* Set up attributes to be attached to the meta-data so that they
kono
parents:
diff changeset
267 will be placed in the correct sections. */
kono
parents:
diff changeset
268 next_runtime_abi_01_init_metadata_attributes ();
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
271 objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
272 get_identifier ("_prop_list_t")));
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 /* Declare type of selector-objects that represent an operation
kono
parents:
diff changeset
275 name. */
kono
parents:
diff changeset
276 /* `struct objc_selector *' */
kono
parents:
diff changeset
277 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
278 get_identifier (TAG_SELECTOR)));
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 build_v1_class_template ();
kono
parents:
diff changeset
281 build_super_template ();
kono
parents:
diff changeset
282 build_v1_protocol_template ();
kono
parents:
diff changeset
283 build_v1_category_template ();
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 /* NB: In order to call one of the ..._stret (struct-returning)
kono
parents:
diff changeset
286 functions, the function *MUST* first be cast to a signature that
kono
parents:
diff changeset
287 corresponds to the actual ObjC method being invoked. This is
kono
parents:
diff changeset
288 what is done by the build_objc_method_call() routine below. */
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 /* id objc_msgSend (id, SEL, ...); */
kono
parents:
diff changeset
291 /* id objc_msgSendNonNil (id, SEL, ...); */
kono
parents:
diff changeset
292 /* id objc_msgSend_stret (id, SEL, ...); */
kono
parents:
diff changeset
293 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
kono
parents:
diff changeset
294 type = build_varargs_function_type_list (objc_object_type,
kono
parents:
diff changeset
295 objc_object_type,
kono
parents:
diff changeset
296 objc_selector_type,
kono
parents:
diff changeset
297 NULL_TREE);
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 umsg_decl = add_builtin_function (TAG_MSGSEND,
kono
parents:
diff changeset
300 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
301 NULL, NULL_TREE);
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
kono
parents:
diff changeset
304 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
305 NULL, NULL_TREE);
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
kono
parents:
diff changeset
308 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
309 NULL, NULL_TREE);
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
kono
parents:
diff changeset
312 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
313 NULL, NULL_TREE);
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 /* These can throw, because the function that gets called can throw
kono
parents:
diff changeset
316 in Obj-C++, or could itself call something that can throw even in
kono
parents:
diff changeset
317 Obj-C. */
kono
parents:
diff changeset
318 TREE_NOTHROW (umsg_decl) = 0;
kono
parents:
diff changeset
319 TREE_NOTHROW (umsg_nonnil_decl) = 0;
kono
parents:
diff changeset
320 TREE_NOTHROW (umsg_stret_decl) = 0;
kono
parents:
diff changeset
321 TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 /* id objc_msgSend_Fast (id, SEL, ...)
kono
parents:
diff changeset
324 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
kono
parents:
diff changeset
325 #ifdef OFFS_MSGSEND_FAST
kono
parents:
diff changeset
326 umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
kono
parents:
diff changeset
327 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
328 NULL, NULL_TREE);
kono
parents:
diff changeset
329 TREE_NOTHROW (umsg_fast_decl) = 0;
kono
parents:
diff changeset
330 DECL_ATTRIBUTES (umsg_fast_decl)
kono
parents:
diff changeset
331 = tree_cons (get_identifier ("hard_coded_address"),
kono
parents:
diff changeset
332 build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
kono
parents:
diff changeset
333 NULL_TREE);
kono
parents:
diff changeset
334 #else
kono
parents:
diff changeset
335 /* No direct dispatch available. */
kono
parents:
diff changeset
336 umsg_fast_decl = umsg_decl;
kono
parents:
diff changeset
337 #endif
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
kono
parents:
diff changeset
340 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
kono
parents:
diff changeset
341 type = build_varargs_function_type_list (objc_object_type,
kono
parents:
diff changeset
342 objc_super_type,
kono
parents:
diff changeset
343 objc_selector_type,
kono
parents:
diff changeset
344 NULL_TREE);
kono
parents:
diff changeset
345 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
kono
parents:
diff changeset
346 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
347 NULL, NULL_TREE);
kono
parents:
diff changeset
348 umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
kono
parents:
diff changeset
349 type, 0, NOT_BUILT_IN, 0,
kono
parents:
diff changeset
350 NULL_TREE);
kono
parents:
diff changeset
351 TREE_NOTHROW (umsg_super_decl) = 0;
kono
parents:
diff changeset
352 TREE_NOTHROW (umsg_super_stret_decl) = 0;
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 type = build_function_type_list (objc_object_type,
kono
parents:
diff changeset
355 const_string_type_node,
kono
parents:
diff changeset
356 NULL_TREE);
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 /* id objc_getClass (const char *); */
kono
parents:
diff changeset
359 objc_get_class_decl
kono
parents:
diff changeset
360 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
361 NULL, NULL_TREE);
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 /* id objc_getMetaClass (const char *); */
kono
parents:
diff changeset
364 objc_get_meta_class_decl
kono
parents:
diff changeset
365 = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 /* This is the type of all of the following functions
kono
parents:
diff changeset
368 objc_copyStruct(). */
kono
parents:
diff changeset
369 type = build_function_type_list (void_type_node,
kono
parents:
diff changeset
370 ptr_type_node,
kono
parents:
diff changeset
371 const_ptr_type_node,
kono
parents:
diff changeset
372 ptrdiff_type_node,
kono
parents:
diff changeset
373 boolean_type_node,
kono
parents:
diff changeset
374 boolean_type_node,
kono
parents:
diff changeset
375 NULL_TREE);
kono
parents:
diff changeset
376 /* Declare the following function:
kono
parents:
diff changeset
377 void
kono
parents:
diff changeset
378 objc_copyStruct (void *destination, const void *source,
kono
parents:
diff changeset
379 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
kono
parents:
diff changeset
380 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
kono
parents:
diff changeset
381 type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
382 NULL, NULL_TREE);
kono
parents:
diff changeset
383 TREE_NOTHROW (objc_copyStruct_decl) = 0;
kono
parents:
diff changeset
384 objc_getPropertyStruct_decl = NULL_TREE;
kono
parents:
diff changeset
385 objc_setPropertyStruct_decl = NULL_TREE;
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 build_next_objc_exception_stuff ();
kono
parents:
diff changeset
388 if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
kono
parents:
diff changeset
389 using_eh_for_cleanups ();
kono
parents:
diff changeset
390 lang_hooks.eh_runtime_type = objc_eh_runtime_type;
kono
parents:
diff changeset
391 lang_hooks.eh_personality = objc_eh_personality;
kono
parents:
diff changeset
392 }
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 /* --- templates --- */
kono
parents:
diff changeset
395
kono
parents:
diff changeset
396 /* struct _objc_class
kono
parents:
diff changeset
397 {
kono
parents:
diff changeset
398 struct _objc_class *isa;
kono
parents:
diff changeset
399 struct _objc_class *super_class;
kono
parents:
diff changeset
400 char *name;
kono
parents:
diff changeset
401 long version;
kono
parents:
diff changeset
402 long info;
kono
parents:
diff changeset
403 long instance_size;
kono
parents:
diff changeset
404 struct _objc_ivar_list *ivars;
kono
parents:
diff changeset
405 struct _objc_method_list *methods;
kono
parents:
diff changeset
406 struct objc_cache *cache;
kono
parents:
diff changeset
407 struct _objc_protocol_list *protocols;
kono
parents:
diff changeset
408 #if ABI=1
kono
parents:
diff changeset
409 const char *ivar_layout;
kono
parents:
diff changeset
410 struct _objc_class_ext *ext;
kono
parents:
diff changeset
411 #else
kono
parents:
diff changeset
412 void *sel_id;
kono
parents:
diff changeset
413 void *gc_object_type;
kono
parents:
diff changeset
414 #endif
kono
parents:
diff changeset
415 }; */
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
kono
parents:
diff changeset
418 runtime. We generate them for ABI==0 to maintain backward binary
kono
parents:
diff changeset
419 compatibility. */
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 static void
kono
parents:
diff changeset
422 build_v1_class_template (void)
kono
parents:
diff changeset
423 {
kono
parents:
diff changeset
424 tree ptype, decls, *chain = NULL;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 /* struct _objc_class *isa; */
kono
parents:
diff changeset
429 decls = add_field_decl (build_pointer_type (objc_class_template),
kono
parents:
diff changeset
430 "isa", &chain);
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 /* struct _objc_class *super_class; */
kono
parents:
diff changeset
433 add_field_decl (build_pointer_type (objc_class_template),
kono
parents:
diff changeset
434 "super_class", &chain);
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 /* char *name; */
kono
parents:
diff changeset
437 add_field_decl (string_type_node, "name", &chain);
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 /* long version; */
kono
parents:
diff changeset
440 add_field_decl (long_integer_type_node, "version", &chain);
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 /* long info; */
kono
parents:
diff changeset
443 add_field_decl (long_integer_type_node, "info", &chain);
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 /* long instance_size; */
kono
parents:
diff changeset
446 add_field_decl (long_integer_type_node, "instance_size", &chain);
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 /* struct _objc_ivar_list *ivars; */
kono
parents:
diff changeset
449 add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 /* struct _objc_method_list *methods; */
kono
parents:
diff changeset
452 add_field_decl (objc_method_list_ptr, "methods", &chain);
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 /* struct objc_cache *cache; */
kono
parents:
diff changeset
455 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
456 get_identifier ("objc_cache")));
kono
parents:
diff changeset
457 add_field_decl (ptype, "cache", &chain);
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 /* struct _objc_protocol **protocol_list; */
kono
parents:
diff changeset
460 ptype = build_pointer_type (build_pointer_type
kono
parents:
diff changeset
461 (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
462 get_identifier (UTAG_PROTOCOL))));
kono
parents:
diff changeset
463 add_field_decl (ptype, "protocol_list", &chain);
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
466 {
kono
parents:
diff changeset
467 /* const char *ivar_layout; */
kono
parents:
diff changeset
468 add_field_decl (const_string_type_node, "ivar_layout", &chain);
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 /* struct _objc_class_ext *ext; */
kono
parents:
diff changeset
471 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
472 get_identifier (UTAG_CLASS_EXT)));
kono
parents:
diff changeset
473 add_field_decl (ptype, "ext", &chain);
kono
parents:
diff changeset
474 }
kono
parents:
diff changeset
475 else
kono
parents:
diff changeset
476 {
kono
parents:
diff changeset
477 /* void *sel_id; */
kono
parents:
diff changeset
478 add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
kono
parents:
diff changeset
479 /* void *gc_object_type; */
kono
parents:
diff changeset
480 add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
kono
parents:
diff changeset
481 &chain);
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 objc_finish_struct (objc_class_template, decls);
kono
parents:
diff changeset
485 }
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 /* struct _objc_category
kono
parents:
diff changeset
488 {
kono
parents:
diff changeset
489 char *category_name;
kono
parents:
diff changeset
490 char *class_name;
kono
parents:
diff changeset
491 struct _objc_method_list *instance_methods;
kono
parents:
diff changeset
492 struct _objc_method_list *class_methods;
kono
parents:
diff changeset
493 struct _objc_protocol_list *protocols;
kono
parents:
diff changeset
494 #if ABI=1
kono
parents:
diff changeset
495 uint32_t size; // sizeof (struct _objc_category)
kono
parents:
diff changeset
496 struct _objc_property_list *instance_properties; // category's own @property decl.
kono
parents:
diff changeset
497 #endif
kono
parents:
diff changeset
498 }; */
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 static void
kono
parents:
diff changeset
501 build_v1_category_template (void)
kono
parents:
diff changeset
502 {
kono
parents:
diff changeset
503 tree ptype, decls, *chain = NULL;
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 /* char *category_name; */
kono
parents:
diff changeset
508 decls = add_field_decl (string_type_node, "category_name", &chain);
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 /* char *class_name; */
kono
parents:
diff changeset
511 add_field_decl (string_type_node, "class_name", &chain);
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 /* struct _objc_method_list *instance_methods; */
kono
parents:
diff changeset
514 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 /* struct _objc_method_list *class_methods; */
kono
parents:
diff changeset
517 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 /* struct _objc_protocol **protocol_list; */
kono
parents:
diff changeset
520 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
kono
parents:
diff changeset
521 add_field_decl (ptype, "protocol_list", &chain);
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
524 {
kono
parents:
diff changeset
525 add_field_decl (integer_type_node, "size", &chain);
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 /* struct _objc_property_list *instance_properties;
kono
parents:
diff changeset
528 This field describes a category's @property declarations.
kono
parents:
diff changeset
529 Properties from inherited protocols are not included. */
kono
parents:
diff changeset
530 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
531 get_identifier (UTAG_PROPERTY_LIST)));
kono
parents:
diff changeset
532 add_field_decl (ptype, "instance_properties", &chain);
kono
parents:
diff changeset
533 }
kono
parents:
diff changeset
534 objc_finish_struct (objc_category_template, decls);
kono
parents:
diff changeset
535 }
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 /* Begin code generation for protocols...
kono
parents:
diff changeset
538 Modified for ObjC #1 extensions. */
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 /* struct _objc_protocol
kono
parents:
diff changeset
541 {
kono
parents:
diff changeset
542 #if ABI=1
kono
parents:
diff changeset
543 struct _objc_protocol_extension *isa;
kono
parents:
diff changeset
544 #else
kono
parents:
diff changeset
545 struct _objc_class *isa;
kono
parents:
diff changeset
546 #endif
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 char *protocol_name;
kono
parents:
diff changeset
549 struct _objc_protocol **protocol_list;
kono
parents:
diff changeset
550 struct _objc__method_prototype_list *instance_methods;
kono
parents:
diff changeset
551 struct _objc__method_prototype_list *class_methods;
kono
parents:
diff changeset
552 }; */
kono
parents:
diff changeset
553
kono
parents:
diff changeset
554 static void
kono
parents:
diff changeset
555 build_v1_protocol_template (void)
kono
parents:
diff changeset
556 {
kono
parents:
diff changeset
557 tree ptype, decls, *chain = NULL;
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
kono
parents:
diff changeset
560
kono
parents:
diff changeset
561 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
562 /* struct _objc_protocol_extension *isa; */
kono
parents:
diff changeset
563 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
564 get_identifier (UTAG_PROTOCOL_EXT)));
kono
parents:
diff changeset
565 else
kono
parents:
diff changeset
566 /* struct _objc_class *isa; */
kono
parents:
diff changeset
567 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
568 get_identifier (UTAG_CLASS)));
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 decls = add_field_decl (ptype, "isa", &chain);
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 /* char *protocol_name; */
kono
parents:
diff changeset
573 add_field_decl (string_type_node, "protocol_name", &chain);
kono
parents:
diff changeset
574
kono
parents:
diff changeset
575 /* struct _objc_protocol **protocol_list; */
kono
parents:
diff changeset
576 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
kono
parents:
diff changeset
577 add_field_decl (ptype, "protocol_list", &chain);
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 /* struct _objc__method_prototype_list *instance_methods; */
kono
parents:
diff changeset
580 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 /* struct _objc__method_prototype_list *class_methods; */
kono
parents:
diff changeset
583 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 objc_finish_struct (objc_protocol_template, decls);
kono
parents:
diff changeset
586 }
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 /* --- names, decls identifiers --- */
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 static tree
kono
parents:
diff changeset
591 next_runtime_abi_01_super_superclassfield_id (void)
kono
parents:
diff changeset
592 {
kono
parents:
diff changeset
593 if (!super_superclassfield_id)
kono
parents:
diff changeset
594 super_superclassfield_id = get_identifier ("super_class");
kono
parents:
diff changeset
595 return super_superclassfield_id;
kono
parents:
diff changeset
596 }
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 static tree
kono
parents:
diff changeset
599 next_runtime_abi_01_class_decl (tree klass)
kono
parents:
diff changeset
600 {
kono
parents:
diff changeset
601 tree decl;
kono
parents:
diff changeset
602 char buf[BUFSIZE];
kono
parents:
diff changeset
603 snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
kono
parents:
diff changeset
604 IDENTIFIER_POINTER (CLASS_NAME (klass)));
kono
parents:
diff changeset
605 decl = start_var_decl (objc_class_template, buf);
kono
parents:
diff changeset
606 OBJCMETA (decl, objc_meta, meta_class);
kono
parents:
diff changeset
607 return decl;
kono
parents:
diff changeset
608 }
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 static tree
kono
parents:
diff changeset
611 next_runtime_abi_01_metaclass_decl (tree klass)
kono
parents:
diff changeset
612 {
kono
parents:
diff changeset
613 tree decl;
kono
parents:
diff changeset
614 char buf[BUFSIZE];
kono
parents:
diff changeset
615 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
kono
parents:
diff changeset
616 IDENTIFIER_POINTER (CLASS_NAME (klass)));
kono
parents:
diff changeset
617 decl = start_var_decl (objc_class_template, buf);
kono
parents:
diff changeset
618 OBJCMETA (decl, objc_meta, meta_metaclass);
kono
parents:
diff changeset
619 return decl;
kono
parents:
diff changeset
620 }
kono
parents:
diff changeset
621
kono
parents:
diff changeset
622 static tree
kono
parents:
diff changeset
623 next_runtime_abi_01_category_decl (tree klass)
kono
parents:
diff changeset
624 {
kono
parents:
diff changeset
625 tree decl;
kono
parents:
diff changeset
626 char buf[BUFSIZE];
kono
parents:
diff changeset
627 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
kono
parents:
diff changeset
628 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
kono
parents:
diff changeset
629 IDENTIFIER_POINTER (CLASS_NAME (klass)));
kono
parents:
diff changeset
630 decl = start_var_decl (objc_category_template, buf);
kono
parents:
diff changeset
631 OBJCMETA (decl, objc_meta, meta_category);
kono
parents:
diff changeset
632 return decl;
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 static tree
kono
parents:
diff changeset
636 next_runtime_abi_01_protocol_decl (tree p)
kono
parents:
diff changeset
637 {
kono
parents:
diff changeset
638 tree decl;
kono
parents:
diff changeset
639 char buf[BUFSIZE];
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
kono
parents:
diff changeset
644 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
kono
parents:
diff changeset
645 decl = start_var_decl (objc_protocol_template, buf);
kono
parents:
diff changeset
646 OBJCMETA (decl, objc_meta, meta_protocol);
kono
parents:
diff changeset
647 return decl;
kono
parents:
diff changeset
648 }
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 static tree
kono
parents:
diff changeset
651 next_runtime_abi_01_string_decl (tree type, const char *name, string_section where)
kono
parents:
diff changeset
652 {
kono
parents:
diff changeset
653 tree var = start_var_decl (type, name);
kono
parents:
diff changeset
654 switch (where)
kono
parents:
diff changeset
655 {
kono
parents:
diff changeset
656 case class_names:
kono
parents:
diff changeset
657 OBJCMETA (var, objc_meta, meta_class_name);
kono
parents:
diff changeset
658 break;
kono
parents:
diff changeset
659 case meth_var_names:
kono
parents:
diff changeset
660 OBJCMETA (var, objc_meta, meta_meth_name);
kono
parents:
diff changeset
661 break;
kono
parents:
diff changeset
662 case meth_var_types:
kono
parents:
diff changeset
663 OBJCMETA (var, objc_meta, meta_meth_type);
kono
parents:
diff changeset
664 break;
kono
parents:
diff changeset
665 case prop_names_attr:
kono
parents:
diff changeset
666 OBJCMETA (var, objc_meta, meta_prop_name_attr);
kono
parents:
diff changeset
667 break;
kono
parents:
diff changeset
668 default:
kono
parents:
diff changeset
669 OBJCMETA (var, objc_meta, meta_base);
kono
parents:
diff changeset
670 break;
kono
parents:
diff changeset
671 }
kono
parents:
diff changeset
672 return var;
kono
parents:
diff changeset
673 }
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 /* --- entry --- */
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 static GTY(()) int class_reference_idx;
kono
parents:
diff changeset
678
kono
parents:
diff changeset
679 static tree
kono
parents:
diff changeset
680 build_class_reference_decl (void)
kono
parents:
diff changeset
681 {
kono
parents:
diff changeset
682 tree decl;
kono
parents:
diff changeset
683 char buf[BUFSIZE];
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
kono
parents:
diff changeset
686 decl = start_var_decl (objc_class_type, buf);
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 return decl;
kono
parents:
diff changeset
689 }
kono
parents:
diff changeset
690
kono
parents:
diff changeset
691 static tree
kono
parents:
diff changeset
692 next_runtime_abi_01_get_class_reference (tree ident)
kono
parents:
diff changeset
693 {
kono
parents:
diff changeset
694 if (!flag_zero_link)
kono
parents:
diff changeset
695 {
kono
parents:
diff changeset
696 tree *chain;
kono
parents:
diff changeset
697 tree decl;
kono
parents:
diff changeset
698
kono
parents:
diff changeset
699 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
kono
parents:
diff changeset
700 if (TREE_VALUE (*chain) == ident)
kono
parents:
diff changeset
701 {
kono
parents:
diff changeset
702 if (! TREE_PURPOSE (*chain))
kono
parents:
diff changeset
703 TREE_PURPOSE (*chain) = build_class_reference_decl ();
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 return TREE_PURPOSE (*chain);
kono
parents:
diff changeset
706 }
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 decl = build_class_reference_decl ();
kono
parents:
diff changeset
709 *chain = tree_cons (decl, ident, NULL_TREE);
kono
parents:
diff changeset
710 return decl;
kono
parents:
diff changeset
711 }
kono
parents:
diff changeset
712 else
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 tree params;
kono
parents:
diff changeset
715
kono
parents:
diff changeset
716 add_class_reference (ident);
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 params = build_tree_list (NULL_TREE,
kono
parents:
diff changeset
719 my_build_string_pointer
kono
parents:
diff changeset
720 (IDENTIFIER_LENGTH (ident) + 1,
kono
parents:
diff changeset
721 IDENTIFIER_POINTER (ident)));
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 return build_function_call (input_location, objc_get_class_decl, params);
kono
parents:
diff changeset
724 }
kono
parents:
diff changeset
725 }
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 /* Used by build_function_type_for_method. Append the types for
kono
parents:
diff changeset
728 receiver & _cmd at the start of a method argument list to ARGTYPES.
kono
parents:
diff changeset
729 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
kono
parents:
diff changeset
730 trying to define a method or call one. SUPERFLAG says this is for a
kono
parents:
diff changeset
731 send to super. METH may be NULL, in the case that there is no
kono
parents:
diff changeset
732 prototype. */
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 static void
kono
parents:
diff changeset
735 next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
kono
parents:
diff changeset
736 tree meth, int context,
kono
parents:
diff changeset
737 int superflag)
kono
parents:
diff changeset
738 {
kono
parents:
diff changeset
739 tree receiver_type;
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 if (superflag)
kono
parents:
diff changeset
742 receiver_type = objc_super_type;
kono
parents:
diff changeset
743 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
kono
parents:
diff changeset
744 receiver_type = objc_instance_type;
kono
parents:
diff changeset
745 else
kono
parents:
diff changeset
746 receiver_type = objc_object_type;
kono
parents:
diff changeset
747
kono
parents:
diff changeset
748 vec_safe_push (*argtypes, receiver_type);
kono
parents:
diff changeset
749 /* Selector type - will eventually change to `int'. */
kono
parents:
diff changeset
750 vec_safe_push (*argtypes, objc_selector_type);
kono
parents:
diff changeset
751 }
kono
parents:
diff changeset
752
kono
parents:
diff changeset
753 static tree
kono
parents:
diff changeset
754 next_runtime_abi_01_receiver_is_class_object (tree receiver)
kono
parents:
diff changeset
755 {
kono
parents:
diff changeset
756 if (TREE_CODE (receiver) == VAR_DECL
kono
parents:
diff changeset
757 && IS_CLASS (TREE_TYPE (receiver)))
kono
parents:
diff changeset
758 {
kono
parents:
diff changeset
759 /* The receiver is a variable created by build_class_reference_decl. */
kono
parents:
diff changeset
760 tree chain = cls_ref_chain ;
kono
parents:
diff changeset
761 /* Look up the identifier in the relevant chain. */
kono
parents:
diff changeset
762 for (; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
763 if (TREE_PURPOSE (chain) == receiver)
kono
parents:
diff changeset
764 return TREE_VALUE (chain);
kono
parents:
diff changeset
765 }
kono
parents:
diff changeset
766 return NULL_TREE;
kono
parents:
diff changeset
767 }
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 static tree
kono
parents:
diff changeset
770 build_selector_reference_decl (tree ident)
kono
parents:
diff changeset
771 {
kono
parents:
diff changeset
772 tree decl;
kono
parents:
diff changeset
773 char *t, buf[BUFSIZE];
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
kono
parents:
diff changeset
776 t = buf;
kono
parents:
diff changeset
777 while (*t)
kono
parents:
diff changeset
778 {
kono
parents:
diff changeset
779 if (*t==':')
kono
parents:
diff changeset
780 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
kono
parents:
diff changeset
781 t++;
kono
parents:
diff changeset
782 }
kono
parents:
diff changeset
783 decl = start_var_decl (objc_selector_type, buf);
kono
parents:
diff changeset
784 OBJCMETA (decl, objc_meta, meta_sel_refs);
kono
parents:
diff changeset
785 return decl;
kono
parents:
diff changeset
786 }
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 static tree
kono
parents:
diff changeset
789 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
790 tree ident,
kono
parents:
diff changeset
791 tree proto ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
792 {
kono
parents:
diff changeset
793 tree *chain = &sel_ref_chain;
kono
parents:
diff changeset
794 tree expr;
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 while (*chain)
kono
parents:
diff changeset
797 {
kono
parents:
diff changeset
798 if (TREE_VALUE (*chain) == ident)
kono
parents:
diff changeset
799 return TREE_PURPOSE (*chain);
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 chain = &TREE_CHAIN (*chain);
kono
parents:
diff changeset
802 }
kono
parents:
diff changeset
803
kono
parents:
diff changeset
804 expr = build_selector_reference_decl (ident);
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 *chain = tree_cons (expr, ident, NULL_TREE);
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 return expr;
kono
parents:
diff changeset
809 }
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 /* Build a tree expression to send OBJECT the operation SELECTOR,
kono
parents:
diff changeset
812 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
kono
parents:
diff changeset
813 assuming the method has prototype METHOD_PROTOTYPE.
kono
parents:
diff changeset
814 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
kono
parents:
diff changeset
815 LOC is the location of the expression to build.
kono
parents:
diff changeset
816 Use METHOD_PARAMS as list of args to pass to the method.
kono
parents:
diff changeset
817 If SUPER_FLAG is nonzero, we look up the superclass's method. */
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 static tree
kono
parents:
diff changeset
820 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
kono
parents:
diff changeset
821 tree lookup_object, tree selector,
kono
parents:
diff changeset
822 tree method_params)
kono
parents:
diff changeset
823 {
kono
parents:
diff changeset
824 tree sender, sender_cast, method, t;
kono
parents:
diff changeset
825 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
kono
parents:
diff changeset
826 vec<tree, va_gc> *parms;
kono
parents:
diff changeset
827 unsigned nparm = (method_params ? list_length (method_params) : 0);
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 /* If a prototype for the method to be called exists, then cast
kono
parents:
diff changeset
830 the sender's return type and arguments to match that of the method.
kono
parents:
diff changeset
831 Otherwise, leave sender as is. */
kono
parents:
diff changeset
832 tree ret_type
kono
parents:
diff changeset
833 = (method_prototype
kono
parents:
diff changeset
834 ? TREE_VALUE (TREE_TYPE (method_prototype))
kono
parents:
diff changeset
835 : objc_object_type);
kono
parents:
diff changeset
836 tree ftype = build_function_type_for_method (ret_type, method_prototype,
kono
parents:
diff changeset
837 METHOD_REF, super_flag);
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
kono
parents:
diff changeset
840 ftype = build_type_attribute_variant (ftype,
kono
parents:
diff changeset
841 METHOD_TYPE_ATTRIBUTES
kono
parents:
diff changeset
842 (method_prototype));
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 sender_cast = build_pointer_type (ftype);
kono
parents:
diff changeset
845
kono
parents:
diff changeset
846 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
kono
parents:
diff changeset
849 lookup_object = save_expr (lookup_object);
kono
parents:
diff changeset
850
kono
parents:
diff changeset
851 /* Param list + 2 slots for object and selector. */
kono
parents:
diff changeset
852 vec_alloc (parms, nparm + 2);
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 /* If we are returning a struct in memory, and the address
kono
parents:
diff changeset
855 of that memory location is passed as a hidden first
kono
parents:
diff changeset
856 argument, then change which messenger entry point this
kono
parents:
diff changeset
857 expr will call. NB: Note that sender_cast remains
kono
parents:
diff changeset
858 unchanged (it already has a struct return type). */
kono
parents:
diff changeset
859 if (!targetm.calls.struct_value_rtx (0, 0)
kono
parents:
diff changeset
860 && (TREE_CODE (ret_type) == RECORD_TYPE
kono
parents:
diff changeset
861 || TREE_CODE (ret_type) == UNION_TYPE)
kono
parents:
diff changeset
862 && targetm.calls.return_in_memory (ret_type, 0))
kono
parents:
diff changeset
863 sender = (super_flag ? umsg_super_stret_decl
kono
parents:
diff changeset
864 : flag_nil_receivers ? umsg_stret_decl
kono
parents:
diff changeset
865 : umsg_nonnil_stret_decl);
kono
parents:
diff changeset
866 else
kono
parents:
diff changeset
867 sender = (super_flag ? umsg_super_decl
kono
parents:
diff changeset
868 : (flag_nil_receivers ? (flag_objc_direct_dispatch
kono
parents:
diff changeset
869 ? umsg_fast_decl
kono
parents:
diff changeset
870 : umsg_decl)
kono
parents:
diff changeset
871 : umsg_nonnil_decl));
kono
parents:
diff changeset
872 method = build_fold_addr_expr_loc (loc, sender);
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 /* Pass the object to the method. */
kono
parents:
diff changeset
875 parms->quick_push (lookup_object);
kono
parents:
diff changeset
876 /* Pass the selector to the method. */
kono
parents:
diff changeset
877 parms->quick_push (selector);
kono
parents:
diff changeset
878 /* Now append the remainder of the parms. */
kono
parents:
diff changeset
879 if (nparm)
kono
parents:
diff changeset
880 for (; method_params; method_params = TREE_CHAIN (method_params))
kono
parents:
diff changeset
881 parms->quick_push (TREE_VALUE (method_params));
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 /* Build an obj_type_ref, with the correct cast for the method call. */
kono
parents:
diff changeset
884 t = build3 (OBJ_TYPE_REF, sender_cast, method,
kono
parents:
diff changeset
885 lookup_object, size_zero_node);
kono
parents:
diff changeset
886 t = build_function_call_vec (loc, vNULL, t, parms, NULL);
kono
parents:
diff changeset
887 vec_free (parms);
kono
parents:
diff changeset
888 return t;
kono
parents:
diff changeset
889 }
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 static tree
kono
parents:
diff changeset
892 next_runtime_abi_01_build_objc_method_call (location_t loc,
kono
parents:
diff changeset
893 tree method_prototype,
kono
parents:
diff changeset
894 tree receiver,
kono
parents:
diff changeset
895 tree rtype ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
896 tree sel_name,
kono
parents:
diff changeset
897 tree method_params,
kono
parents:
diff changeset
898 int super)
kono
parents:
diff changeset
899 {
kono
parents:
diff changeset
900 tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
kono
parents:
diff changeset
901 NULL_TREE);
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 return build_objc_method_call (loc, super, method_prototype,
kono
parents:
diff changeset
904 receiver, selector, method_params);
kono
parents:
diff changeset
905 }
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 static tree
kono
parents:
diff changeset
908 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
kono
parents:
diff changeset
909 {
kono
parents:
diff changeset
910 tree expr;
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 if (!PROTOCOL_FORWARD_DECL (p))
kono
parents:
diff changeset
913 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
kono
parents:
diff changeset
916 return convert (objc_protocol_type, expr);
kono
parents:
diff changeset
917 }
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 static tree
kono
parents:
diff changeset
922 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
923 tree base, tree id)
kono
parents:
diff changeset
924 {
kono
parents:
diff changeset
925 return objc_build_component_ref (base, id);
kono
parents:
diff changeset
926 }
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 /* We build super class references as we need them (but keep them once
kono
parents:
diff changeset
929 built for the sake of efficiency). */
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 static tree
kono
parents:
diff changeset
932 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
933 struct imp_entry *imp, bool inst_meth)
kono
parents:
diff changeset
934 {
kono
parents:
diff changeset
935 if (inst_meth)
kono
parents:
diff changeset
936 {
kono
parents:
diff changeset
937 if (!ucls_super_ref)
kono
parents:
diff changeset
938 ucls_super_ref =
kono
parents:
diff changeset
939 objc_build_component_ref (imp->class_decl,
kono
parents:
diff changeset
940 get_identifier ("super_class"));
kono
parents:
diff changeset
941 return ucls_super_ref;
kono
parents:
diff changeset
942 }
kono
parents:
diff changeset
943 else
kono
parents:
diff changeset
944 {
kono
parents:
diff changeset
945 if (!uucls_super_ref)
kono
parents:
diff changeset
946 uucls_super_ref =
kono
parents:
diff changeset
947 objc_build_component_ref (imp->meta_decl,
kono
parents:
diff changeset
948 get_identifier ("super_class"));
kono
parents:
diff changeset
949 return uucls_super_ref;
kono
parents:
diff changeset
950 }
kono
parents:
diff changeset
951 }
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 static tree
kono
parents:
diff changeset
954 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
955 struct imp_entry *imp, bool inst_meth)
kono
parents:
diff changeset
956 {
kono
parents:
diff changeset
957 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
kono
parents:
diff changeset
958 tree super_class;
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 if (!flag_zero_link)
kono
parents:
diff changeset
961 {
kono
parents:
diff changeset
962 super_class = objc_get_class_reference (super_name);
kono
parents:
diff changeset
963
kono
parents:
diff changeset
964 if (!inst_meth)
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966 /* If we are in a class method, we must retrieve the
kono
parents:
diff changeset
967 _metaclass_ for the current class, pointed at by
kono
parents:
diff changeset
968 the class's "isa" pointer. The following assumes that
kono
parents:
diff changeset
969 "isa" is the first ivar in a class (which it must be). */
kono
parents:
diff changeset
970 super_class =
kono
parents:
diff changeset
971 build_indirect_ref (input_location,
kono
parents:
diff changeset
972 build_c_cast (input_location,
kono
parents:
diff changeset
973 build_pointer_type (objc_class_type),
kono
parents:
diff changeset
974 super_class),
kono
parents:
diff changeset
975 RO_UNARY_STAR);
kono
parents:
diff changeset
976 return super_class;
kono
parents:
diff changeset
977 }
kono
parents:
diff changeset
978
kono
parents:
diff changeset
979 /* else do it the slow way. */
kono
parents:
diff changeset
980 add_class_reference (super_name);
kono
parents:
diff changeset
981 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
kono
parents:
diff changeset
982 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
kono
parents:
diff changeset
983 IDENTIFIER_POINTER (super_name));
kono
parents:
diff changeset
984 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
kono
parents:
diff changeset
985 return build_function_call (input_location,
kono
parents:
diff changeset
986 super_class,
kono
parents:
diff changeset
987 build_tree_list (NULL_TREE, super_name));
kono
parents:
diff changeset
988 }
kono
parents:
diff changeset
989
kono
parents:
diff changeset
990 static bool
kono
parents:
diff changeset
991 next_runtime_abi_01_setup_const_string_class_decl (void)
kono
parents:
diff changeset
992 {
kono
parents:
diff changeset
993 if (!constant_string_global_id)
kono
parents:
diff changeset
994 {
kono
parents:
diff changeset
995 /* Hopefully, this should not represent a serious limitation. */
kono
parents:
diff changeset
996 char buf[BUFSIZE];
kono
parents:
diff changeset
997 snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
kono
parents:
diff changeset
998 constant_string_global_id = get_identifier (buf);
kono
parents:
diff changeset
999 }
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 string_class_decl = lookup_name (constant_string_global_id);
kono
parents:
diff changeset
1002
kono
parents:
diff changeset
1003 return (string_class_decl != NULL_TREE);
kono
parents:
diff changeset
1004 }
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 static tree
kono
parents:
diff changeset
1007 next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
kono
parents:
diff changeset
1008 int length)
kono
parents:
diff changeset
1009 {
kono
parents:
diff changeset
1010 tree constructor, fields, var;
kono
parents:
diff changeset
1011 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1012
kono
parents:
diff changeset
1013 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
kono
parents:
diff changeset
1014 fields = TYPE_FIELDS (internal_const_str_type);
kono
parents:
diff changeset
1015 CONSTRUCTOR_APPEND_ELT (v, fields,
kono
parents:
diff changeset
1016 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 fields = DECL_CHAIN (fields);
kono
parents:
diff changeset
1019 CONSTRUCTOR_APPEND_ELT (v, fields,
kono
parents:
diff changeset
1020 build_unary_op (loc, ADDR_EXPR, string, 1));
kono
parents:
diff changeset
1021
kono
parents:
diff changeset
1022 /* ??? check if this should be long. */
kono
parents:
diff changeset
1023 fields = DECL_CHAIN (fields);
kono
parents:
diff changeset
1024 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
kono
parents:
diff changeset
1025 constructor = objc_build_constructor (internal_const_str_type, v);
kono
parents:
diff changeset
1026
kono
parents:
diff changeset
1027 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
kono
parents:
diff changeset
1028 DECL_INITIAL (var) = constructor;
kono
parents:
diff changeset
1029 TREE_STATIC (var) = 1;
kono
parents:
diff changeset
1030 DECL_CONTEXT (var) = NULL;
kono
parents:
diff changeset
1031 OBJCMETA (var, objc_meta, meta_const_str);
kono
parents:
diff changeset
1032 return var;
kono
parents:
diff changeset
1033 }
kono
parents:
diff changeset
1034
kono
parents:
diff changeset
1035 /* --- metadata templates --- */
kono
parents:
diff changeset
1036
kono
parents:
diff changeset
1037 /* This routine builds the following type:
kono
parents:
diff changeset
1038 struct _prop_t {
kono
parents:
diff changeset
1039 const char * const name; // property name
kono
parents:
diff changeset
1040 const char * const attributes; // comma-delimited, encoded,
kono
parents:
diff changeset
1041 // property attributes
kono
parents:
diff changeset
1042 };
kono
parents:
diff changeset
1043 */
kono
parents:
diff changeset
1044
kono
parents:
diff changeset
1045 static GTY(()) tree objc_v1_property_template;
kono
parents:
diff changeset
1046
kono
parents:
diff changeset
1047 static tree
kono
parents:
diff changeset
1048 build_v1_property_template (void)
kono
parents:
diff changeset
1049 {
kono
parents:
diff changeset
1050 tree prop_record;
kono
parents:
diff changeset
1051 tree decls, *chain = NULL;
kono
parents:
diff changeset
1052
kono
parents:
diff changeset
1053 prop_record = objc_start_struct (get_identifier ("_prop_t"));
kono
parents:
diff changeset
1054 /* const char * name */
kono
parents:
diff changeset
1055 decls = add_field_decl (string_type_node, "name", &chain);
kono
parents:
diff changeset
1056
kono
parents:
diff changeset
1057 /* const char * attribute */
kono
parents:
diff changeset
1058 add_field_decl (string_type_node, "attribute", &chain);
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 objc_finish_struct (prop_record, decls);
kono
parents:
diff changeset
1061 return prop_record;
kono
parents:
diff changeset
1062 }
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064 /* Build the following type:
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 struct _objc_protocol_extension
kono
parents:
diff changeset
1067 {
kono
parents:
diff changeset
1068 uint32_t size; // sizeof (struct _objc_protocol_extension)
kono
parents:
diff changeset
1069 struct objc_method_list *optional_instance_methods;
kono
parents:
diff changeset
1070 struct objc_method_list *optional_class_methods;
kono
parents:
diff changeset
1071 struct objc_prop_list *instance_properties;
kono
parents:
diff changeset
1072 }
kono
parents:
diff changeset
1073 */
kono
parents:
diff changeset
1074
kono
parents:
diff changeset
1075 static GTY(()) tree objc_protocol_extension_template;
kono
parents:
diff changeset
1076
kono
parents:
diff changeset
1077 static void
kono
parents:
diff changeset
1078 build_v1_objc_protocol_extension_template (void)
kono
parents:
diff changeset
1079 {
kono
parents:
diff changeset
1080 tree decls, *chain = NULL;
kono
parents:
diff changeset
1081
kono
parents:
diff changeset
1082 objc_protocol_extension_template =
kono
parents:
diff changeset
1083 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
kono
parents:
diff changeset
1084
kono
parents:
diff changeset
1085 /* uint32_t size; */
kono
parents:
diff changeset
1086 decls = add_field_decl (integer_type_node, "size", &chain);
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 /* struct objc_method_list *optional_instance_methods; */
kono
parents:
diff changeset
1089 add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
kono
parents:
diff changeset
1090
kono
parents:
diff changeset
1091 /* struct objc_method_list *optional_class_methods; */
kono
parents:
diff changeset
1092 add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
kono
parents:
diff changeset
1093
kono
parents:
diff changeset
1094 /* struct objc_prop_list *instance_properties; */
kono
parents:
diff changeset
1095 add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
kono
parents:
diff changeset
1096
kono
parents:
diff changeset
1097 objc_finish_struct (objc_protocol_extension_template, decls);
kono
parents:
diff changeset
1098 }
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 /* This routine build following struct type:
kono
parents:
diff changeset
1101 struct _objc_class_ext
kono
parents:
diff changeset
1102 {
kono
parents:
diff changeset
1103 uint32_t size; // sizeof(struct _objc_class_ext)
kono
parents:
diff changeset
1104 const char *weak_ivar_layout;
kono
parents:
diff changeset
1105 struct _prop_list_t *properties;
kono
parents:
diff changeset
1106 }
kono
parents:
diff changeset
1107 */
kono
parents:
diff changeset
1108
kono
parents:
diff changeset
1109 static GTY(()) tree objc_class_ext_template;
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 static void
kono
parents:
diff changeset
1112 build_objc_class_ext_template (void)
kono
parents:
diff changeset
1113 {
kono
parents:
diff changeset
1114 tree ptrt, decls, *chain = NULL;
kono
parents:
diff changeset
1115
kono
parents:
diff changeset
1116 objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
kono
parents:
diff changeset
1117
kono
parents:
diff changeset
1118 /* uint32_t size; */
kono
parents:
diff changeset
1119 decls = add_field_decl (integer_type_node, "size", &chain);
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 /* const char *weak_ivar_layout; */
kono
parents:
diff changeset
1122 add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
kono
parents:
diff changeset
1123
kono
parents:
diff changeset
1124 /* struct _prop_list_t *properties; */
kono
parents:
diff changeset
1125 ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
1126 get_identifier(UTAG_PROPERTY_LIST)));
kono
parents:
diff changeset
1127 add_field_decl (ptrt, "properties", &chain);
kono
parents:
diff changeset
1128
kono
parents:
diff changeset
1129 objc_finish_struct (objc_class_ext_template, decls);
kono
parents:
diff changeset
1130 }
kono
parents:
diff changeset
1131
kono
parents:
diff changeset
1132 static void
kono
parents:
diff changeset
1133 build_metadata_templates (void)
kono
parents:
diff changeset
1134 {
kono
parents:
diff changeset
1135
kono
parents:
diff changeset
1136 if (!objc_method_template)
kono
parents:
diff changeset
1137 objc_method_template = build_method_template ();
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 }
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 /* --- emit metadata --- */
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 static tree
kono
parents:
diff changeset
1146 generate_v1_meth_descriptor_table (tree chain, tree protocol,
kono
parents:
diff changeset
1147 const char *prefix, tree attr)
kono
parents:
diff changeset
1148 {
kono
parents:
diff changeset
1149 tree method_list_template, initlist, decl;
kono
parents:
diff changeset
1150 int size;
kono
parents:
diff changeset
1151 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1152 char buf[BUFSIZE];
kono
parents:
diff changeset
1153
kono
parents:
diff changeset
1154 if (!chain || !prefix)
kono
parents:
diff changeset
1155 return NULL_TREE;
kono
parents:
diff changeset
1156
kono
parents:
diff changeset
1157 if (!objc_method_prototype_template)
kono
parents:
diff changeset
1158 objc_method_prototype_template = build_method_prototype_template ();
kono
parents:
diff changeset
1159
kono
parents:
diff changeset
1160 size = list_length (chain);
kono
parents:
diff changeset
1161 method_list_template =
kono
parents:
diff changeset
1162 build_method_prototype_list_template (objc_method_prototype_template,
kono
parents:
diff changeset
1163 size);
kono
parents:
diff changeset
1164 snprintf (buf, BUFSIZE, "%s_%s", prefix,
kono
parents:
diff changeset
1165 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
kono
parents:
diff changeset
1166
kono
parents:
diff changeset
1167 decl = start_var_decl (method_list_template, buf);
kono
parents:
diff changeset
1168
kono
parents:
diff changeset
1169 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
kono
parents:
diff changeset
1170 initlist =
kono
parents:
diff changeset
1171 build_descriptor_table_initializer (objc_method_prototype_template,
kono
parents:
diff changeset
1172 chain);
kono
parents:
diff changeset
1173 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
kono
parents:
diff changeset
1174 /* Get into the right section. */
kono
parents:
diff changeset
1175 OBJCMETA (decl, objc_meta, attr);
kono
parents:
diff changeset
1176 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
kono
parents:
diff changeset
1177 return decl;
kono
parents:
diff changeset
1178 }
kono
parents:
diff changeset
1179
kono
parents:
diff changeset
1180 /* Build protocol ext =
kono
parents:
diff changeset
1181 {size, opt_instance_meth, opt_class_meth, instance_props};
kono
parents:
diff changeset
1182 or NULL_TREE if none are present. */
kono
parents:
diff changeset
1183
kono
parents:
diff changeset
1184 static tree
kono
parents:
diff changeset
1185 generate_v1_objc_protocol_extension (tree proto_interface,
kono
parents:
diff changeset
1186 tree opt_instance_meth,
kono
parents:
diff changeset
1187 tree opt_class_meth,
kono
parents:
diff changeset
1188 tree instance_props)
kono
parents:
diff changeset
1189 {
kono
parents:
diff changeset
1190 int size;
kono
parents:
diff changeset
1191 location_t loc;
kono
parents:
diff changeset
1192 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1193 tree decl, expr;
kono
parents:
diff changeset
1194 char buf[BUFSIZE];
kono
parents:
diff changeset
1195
kono
parents:
diff changeset
1196 /* If there are no extensions, then don't bother... */
kono
parents:
diff changeset
1197 if (!opt_instance_meth && !opt_class_meth && !instance_props)
kono
parents:
diff changeset
1198 return NULL_TREE;
kono
parents:
diff changeset
1199
kono
parents:
diff changeset
1200 if (!objc_protocol_extension_template)
kono
parents:
diff changeset
1201 build_v1_objc_protocol_extension_template ();
kono
parents:
diff changeset
1202
kono
parents:
diff changeset
1203 /* uint32_t size */
kono
parents:
diff changeset
1204 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
kono
parents:
diff changeset
1205 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
kono
parents:
diff changeset
1206
kono
parents:
diff changeset
1207 /* Try for meaningful diagnostics. */
kono
parents:
diff changeset
1208 loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
kono
parents:
diff changeset
1209
kono
parents:
diff changeset
1210 /* struct objc_method_list *optional_instance_methods; */
kono
parents:
diff changeset
1211 if (opt_instance_meth)
kono
parents:
diff changeset
1212 expr = convert (objc_method_list_ptr,
kono
parents:
diff changeset
1213 build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
kono
parents:
diff changeset
1214 else
kono
parents:
diff changeset
1215 expr = convert (objc_method_list_ptr, null_pointer_node);
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1218
kono
parents:
diff changeset
1219 /* struct objc_method_list *optional_class_methods; */
kono
parents:
diff changeset
1220 if (opt_class_meth)
kono
parents:
diff changeset
1221 expr = convert (objc_method_list_ptr,
kono
parents:
diff changeset
1222 build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
kono
parents:
diff changeset
1223 else
kono
parents:
diff changeset
1224 expr = convert (objc_method_list_ptr, null_pointer_node);
kono
parents:
diff changeset
1225
kono
parents:
diff changeset
1226 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1227 /* struct objc_prop_list *instance_properties; */
kono
parents:
diff changeset
1228 if (instance_props)
kono
parents:
diff changeset
1229 expr = convert (objc_prop_list_ptr,
kono
parents:
diff changeset
1230 build_unary_op (loc, ADDR_EXPR, instance_props, 0));
kono
parents:
diff changeset
1231 else
kono
parents:
diff changeset
1232 expr = convert (objc_prop_list_ptr, null_pointer_node);
kono
parents:
diff changeset
1233
kono
parents:
diff changeset
1234 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1235 snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
kono
parents:
diff changeset
1236 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
kono
parents:
diff changeset
1237
kono
parents:
diff changeset
1238 decl = start_var_decl (objc_protocol_extension_template, buf);
kono
parents:
diff changeset
1239 expr = objc_build_constructor (TREE_TYPE (decl), v);
kono
parents:
diff changeset
1240 OBJCMETA (decl, objc_meta, meta_protocol_extension);
kono
parents:
diff changeset
1241 finish_var_decl (decl, expr);
kono
parents:
diff changeset
1242 return decl;
kono
parents:
diff changeset
1243 }
kono
parents:
diff changeset
1244
kono
parents:
diff changeset
1245 /* This routine builds the following type:
kono
parents:
diff changeset
1246 struct _prop_list_t {
kono
parents:
diff changeset
1247 uint32_t entsize; // sizeof (struct _prop_t)
kono
parents:
diff changeset
1248 uint32_t prop_count;
kono
parents:
diff changeset
1249 struct _prop_t prop_list [prop_count];
kono
parents:
diff changeset
1250 }
kono
parents:
diff changeset
1251 */
kono
parents:
diff changeset
1252
kono
parents:
diff changeset
1253 static tree
kono
parents:
diff changeset
1254 build_v1_property_list_template (tree list_type, int size)
kono
parents:
diff changeset
1255 {
kono
parents:
diff changeset
1256 tree property_list_t_record;
kono
parents:
diff changeset
1257 tree array_type, decls, *chain = NULL;
kono
parents:
diff changeset
1258
kono
parents:
diff changeset
1259 /* anonymous. */
kono
parents:
diff changeset
1260 property_list_t_record = objc_start_struct (NULL_TREE);
kono
parents:
diff changeset
1261
kono
parents:
diff changeset
1262 /* uint32_t const entsize */
kono
parents:
diff changeset
1263 decls = add_field_decl (integer_type_node, "entsize", &chain);
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 /* int prop_count */
kono
parents:
diff changeset
1266 add_field_decl (integer_type_node, "prop_count", &chain);
kono
parents:
diff changeset
1267
kono
parents:
diff changeset
1268 /* struct _prop_t prop_list[]; */
kono
parents:
diff changeset
1269 array_type = build_sized_array_type (list_type, size);
kono
parents:
diff changeset
1270 add_field_decl (array_type, "prop_list", &chain);
kono
parents:
diff changeset
1271
kono
parents:
diff changeset
1272 objc_finish_struct (property_list_t_record, decls);
kono
parents:
diff changeset
1273 return property_list_t_record;
kono
parents:
diff changeset
1274 }
kono
parents:
diff changeset
1275
kono
parents:
diff changeset
1276 /* This routine builds the initializer list to initialize the
kono
parents:
diff changeset
1277 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
kono
parents:
diff changeset
1278
kono
parents:
diff changeset
1279 static tree
kono
parents:
diff changeset
1280 build_v1_property_table_initializer (tree type, tree context)
kono
parents:
diff changeset
1281 {
kono
parents:
diff changeset
1282 tree x;
kono
parents:
diff changeset
1283 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
1284
kono
parents:
diff changeset
1285 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
kono
parents:
diff changeset
1286 x = CLASS_PROPERTY_DECL (context);
kono
parents:
diff changeset
1287 else
kono
parents:
diff changeset
1288 x = IMPL_PROPERTY_DECL (context);
kono
parents:
diff changeset
1289
kono
parents:
diff changeset
1290 for (; x; x = TREE_CHAIN (x))
kono
parents:
diff changeset
1291 {
kono
parents:
diff changeset
1292 vec<constructor_elt, va_gc> *elemlist = NULL;
kono
parents:
diff changeset
1293 tree attribute, name_ident = PROPERTY_NAME (x);
kono
parents:
diff changeset
1294
kono
parents:
diff changeset
1295 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
kono
parents:
diff changeset
1296 add_objc_string (name_ident, prop_names_attr));
kono
parents:
diff changeset
1297
kono
parents:
diff changeset
1298 attribute = objc_v2_encode_prop_attr (x);
kono
parents:
diff changeset
1299 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
kono
parents:
diff changeset
1300 add_objc_string (attribute, prop_names_attr));
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
kono
parents:
diff changeset
1303 objc_build_constructor (type, elemlist));
kono
parents:
diff changeset
1304 }
kono
parents:
diff changeset
1305
kono
parents:
diff changeset
1306 return objc_build_constructor (build_array_type (type, 0),inits);
kono
parents:
diff changeset
1307 }
kono
parents:
diff changeset
1308
kono
parents:
diff changeset
1309 /* This routine builds the 'struct _prop_list_t' variable declaration and
kono
parents:
diff changeset
1310 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
kono
parents:
diff changeset
1311 NAME is the internal name of this variable, SIZE is number of properties
kono
parents:
diff changeset
1312 for this class and LIST is the initializer list for its 'prop_list' field. */
kono
parents:
diff changeset
1313
kono
parents:
diff changeset
1314 static tree
kono
parents:
diff changeset
1315 generate_v1_property_table (tree context, tree klass_ctxt)
kono
parents:
diff changeset
1316 {
kono
parents:
diff changeset
1317 tree x, decl, initlist, property_list_template;
kono
parents:
diff changeset
1318 bool is_proto = false;
kono
parents:
diff changeset
1319 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
1320 int init_val, size = 0;
kono
parents:
diff changeset
1321 char buf[BUFSIZE];
kono
parents:
diff changeset
1322
kono
parents:
diff changeset
1323 if (context)
kono
parents:
diff changeset
1324 {
kono
parents:
diff changeset
1325 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
kono
parents:
diff changeset
1326 x = CLASS_PROPERTY_DECL (context);
kono
parents:
diff changeset
1327 is_proto = true;
kono
parents:
diff changeset
1328 }
kono
parents:
diff changeset
1329 else
kono
parents:
diff changeset
1330 x = IMPL_PROPERTY_DECL (klass_ctxt);
kono
parents:
diff changeset
1331
kono
parents:
diff changeset
1332 for (; x; x = TREE_CHAIN (x))
kono
parents:
diff changeset
1333 size++;
kono
parents:
diff changeset
1334
kono
parents:
diff changeset
1335 if (size == 0)
kono
parents:
diff changeset
1336 return NULL_TREE;
kono
parents:
diff changeset
1337
kono
parents:
diff changeset
1338 if (!objc_v1_property_template)
kono
parents:
diff changeset
1339 objc_v1_property_template = build_v1_property_template ();
kono
parents:
diff changeset
1340
kono
parents:
diff changeset
1341 property_list_template =
kono
parents:
diff changeset
1342 build_v1_property_list_template (objc_v1_property_template,
kono
parents:
diff changeset
1343 size);
kono
parents:
diff changeset
1344 initlist = build_v1_property_table_initializer (objc_v1_property_template,
kono
parents:
diff changeset
1345 is_proto ? context
kono
parents:
diff changeset
1346 : klass_ctxt);
kono
parents:
diff changeset
1347
kono
parents:
diff changeset
1348 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
kono
parents:
diff changeset
1349 if (is_proto)
kono
parents:
diff changeset
1350 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
kono
parents:
diff changeset
1351 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
kono
parents:
diff changeset
1352 else
kono
parents:
diff changeset
1353 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
kono
parents:
diff changeset
1354 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
kono
parents:
diff changeset
1355
kono
parents:
diff changeset
1356 decl = start_var_decl (property_list_template, buf);
kono
parents:
diff changeset
1357 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
kono
parents:
diff changeset
1358 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
kono
parents:
diff changeset
1359 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
kono
parents:
diff changeset
1360 x = objc_build_constructor (TREE_TYPE (decl), inits);
kono
parents:
diff changeset
1361 OBJCMETA (decl, objc_meta, meta_proplist);
kono
parents:
diff changeset
1362 finish_var_decl (decl, x);
kono
parents:
diff changeset
1363 return decl;
kono
parents:
diff changeset
1364 }
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 static tree
kono
parents:
diff changeset
1367 generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
kono
parents:
diff changeset
1368 {
kono
parents:
diff changeset
1369 tree array_type, ptype, refs_decl, lproto, e, plist, attr;
kono
parents:
diff changeset
1370 int size = 0;
kono
parents:
diff changeset
1371 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1372 char buf[BUFSIZE];
kono
parents:
diff changeset
1373
kono
parents:
diff changeset
1374 switch (TREE_CODE (i_or_p))
kono
parents:
diff changeset
1375 {
kono
parents:
diff changeset
1376 case CLASS_INTERFACE_TYPE:
kono
parents:
diff changeset
1377 case CATEGORY_INTERFACE_TYPE:
kono
parents:
diff changeset
1378 plist = CLASS_PROTOCOL_LIST (i_or_p);
kono
parents:
diff changeset
1379 break;
kono
parents:
diff changeset
1380 case PROTOCOL_INTERFACE_TYPE:
kono
parents:
diff changeset
1381 plist = PROTOCOL_LIST (i_or_p);
kono
parents:
diff changeset
1382 break;
kono
parents:
diff changeset
1383 default:
kono
parents:
diff changeset
1384 gcc_unreachable ();
kono
parents:
diff changeset
1385 }
kono
parents:
diff changeset
1386
kono
parents:
diff changeset
1387 /* Compute size. */
kono
parents:
diff changeset
1388 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
kono
parents:
diff changeset
1389 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
kono
parents:
diff changeset
1390 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
kono
parents:
diff changeset
1391 size++;
kono
parents:
diff changeset
1392
kono
parents:
diff changeset
1393 /* Build initializer. */
kono
parents:
diff changeset
1394 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
kono
parents:
diff changeset
1395 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
kono
parents:
diff changeset
1396 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
kono
parents:
diff changeset
1397
kono
parents:
diff changeset
1398 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
kono
parents:
diff changeset
1399 {
kono
parents:
diff changeset
1400 tree pval = TREE_VALUE (lproto);
kono
parents:
diff changeset
1401
kono
parents:
diff changeset
1402 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
kono
parents:
diff changeset
1403 && PROTOCOL_FORWARD_DECL (pval))
kono
parents:
diff changeset
1404 {
kono
parents:
diff changeset
1405 tree fwref = PROTOCOL_FORWARD_DECL (pval);
kono
parents:
diff changeset
1406 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
kono
parents:
diff changeset
1407 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
kono
parents:
diff changeset
1408 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
kono
parents:
diff changeset
1409 }
kono
parents:
diff changeset
1410 }
kono
parents:
diff changeset
1411
kono
parents:
diff changeset
1412 /* static struct objc_protocol *refs[n]; */
kono
parents:
diff changeset
1413 switch (TREE_CODE (i_or_p))
kono
parents:
diff changeset
1414 {
kono
parents:
diff changeset
1415 case PROTOCOL_INTERFACE_TYPE:
kono
parents:
diff changeset
1416 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
kono
parents:
diff changeset
1417 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
kono
parents:
diff changeset
1418 attr = meta_proto_ref;
kono
parents:
diff changeset
1419 break;
kono
parents:
diff changeset
1420 case CLASS_INTERFACE_TYPE:
kono
parents:
diff changeset
1421 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
kono
parents:
diff changeset
1422 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
kono
parents:
diff changeset
1423 attr = meta_clas_prot;
kono
parents:
diff changeset
1424 break;
kono
parents:
diff changeset
1425 case CATEGORY_INTERFACE_TYPE:
kono
parents:
diff changeset
1426 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
kono
parents:
diff changeset
1427 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
kono
parents:
diff changeset
1428 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
kono
parents:
diff changeset
1429 attr = meta_catg_prot;
kono
parents:
diff changeset
1430 break;
kono
parents:
diff changeset
1431 default:
kono
parents:
diff changeset
1432 gcc_unreachable ();
kono
parents:
diff changeset
1433 }
kono
parents:
diff changeset
1434
kono
parents:
diff changeset
1435 ptype = build_pointer_type (objc_protocol_template);
kono
parents:
diff changeset
1436 array_type = build_sized_array_type (ptype, size + 3);
kono
parents:
diff changeset
1437 refs_decl = start_var_decl (array_type, buf);
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 OBJCMETA (refs_decl, objc_meta, attr);
kono
parents:
diff changeset
1440 finish_var_decl (refs_decl,
kono
parents:
diff changeset
1441 objc_build_constructor (TREE_TYPE (refs_decl), v));
kono
parents:
diff changeset
1442
kono
parents:
diff changeset
1443 return refs_decl;
kono
parents:
diff changeset
1444 }
kono
parents:
diff changeset
1445
kono
parents:
diff changeset
1446 static tree
kono
parents:
diff changeset
1447 build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
kono
parents:
diff changeset
1448 tree inst_methods, tree class_methods,
kono
parents:
diff changeset
1449 tree protocol_ext)
kono
parents:
diff changeset
1450 {
kono
parents:
diff changeset
1451 tree expr, ttyp;
kono
parents:
diff changeset
1452 location_t loc;
kono
parents:
diff changeset
1453 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
1454
kono
parents:
diff changeset
1455 if (!objc_protocol_extension_template)
kono
parents:
diff changeset
1456 build_v1_objc_protocol_extension_template ();
kono
parents:
diff changeset
1457
kono
parents:
diff changeset
1458 /* TODO: find a better representation of location from the inputs. */
kono
parents:
diff changeset
1459 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
1460 ttyp = build_pointer_type (objc_protocol_extension_template);
kono
parents:
diff changeset
1461 /* Instead of jamming the protocol version number into the isa, we pass
kono
parents:
diff changeset
1462 either a pointer to the protocol extension - or NULL. */
kono
parents:
diff changeset
1463 if (protocol_ext)
kono
parents:
diff changeset
1464 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
kono
parents:
diff changeset
1465 else
kono
parents:
diff changeset
1466 expr = convert (ttyp, null_pointer_node);
kono
parents:
diff changeset
1467
kono
parents:
diff changeset
1468 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
kono
parents:
diff changeset
1469 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
kono
parents:
diff changeset
1470 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
kono
parents:
diff changeset
1471
kono
parents:
diff changeset
1472 ttyp = objc_method_proto_list_ptr;
kono
parents:
diff changeset
1473 if (inst_methods)
kono
parents:
diff changeset
1474 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
kono
parents:
diff changeset
1475 else
kono
parents:
diff changeset
1476 expr = convert (ttyp, null_pointer_node);
kono
parents:
diff changeset
1477 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
kono
parents:
diff changeset
1478
kono
parents:
diff changeset
1479 if (class_methods)
kono
parents:
diff changeset
1480 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
kono
parents:
diff changeset
1481 else
kono
parents:
diff changeset
1482 expr = convert (ttyp, null_pointer_node);
kono
parents:
diff changeset
1483 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 return objc_build_constructor (type, inits);
kono
parents:
diff changeset
1486 }
kono
parents:
diff changeset
1487
kono
parents:
diff changeset
1488 /* An updated version of generate_protocols () that emit the protocol
kono
parents:
diff changeset
1489 extension for ABI=1. */
kono
parents:
diff changeset
1490
kono
parents:
diff changeset
1491 /* For each protocol which was referenced either from a @protocol()
kono
parents:
diff changeset
1492 expression, or because a class/category implements it (then a
kono
parents:
diff changeset
1493 pointer to the protocol is stored in the struct describing the
kono
parents:
diff changeset
1494 class/category), we create a statically allocated instance of the
kono
parents:
diff changeset
1495 Protocol class. The code is written in such a way as to generate
kono
parents:
diff changeset
1496 as few Protocol objects as possible; we generate a unique Protocol
kono
parents:
diff changeset
1497 instance for each protocol, and we don't generate a Protocol
kono
parents:
diff changeset
1498 instance if the protocol is never referenced (either from a
kono
parents:
diff changeset
1499 @protocol() or from a class/category implementation). These
kono
parents:
diff changeset
1500 statically allocated objects can be referred to via the static
kono
parents:
diff changeset
1501 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 The statically allocated Protocol objects that we generate here
kono
parents:
diff changeset
1504 need to be fixed up at runtime in order to be used: the 'isa'
kono
parents:
diff changeset
1505 pointer of the objects need to be set up to point to the 'Protocol'
kono
parents:
diff changeset
1506 class, as known at runtime.
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508 The NeXT runtime fixes up all protocols at program startup time,
kono
parents:
diff changeset
1509 before main() is entered. It uses a low-level trick to look up all
kono
parents:
diff changeset
1510 those symbols, then loops on them and fixes them up. */
kono
parents:
diff changeset
1511
kono
parents:
diff changeset
1512 /* TODO: finish getting rid of passing stuff around in globals. */
kono
parents:
diff changeset
1513
kono
parents:
diff changeset
1514 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
kono
parents:
diff changeset
1515 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
kono
parents:
diff changeset
1516 static GTY(()) tree V1_ProtocolExt_decl;
kono
parents:
diff changeset
1517 static GTY(()) tree V1_Property_decl;
kono
parents:
diff changeset
1518
kono
parents:
diff changeset
1519 static void
kono
parents:
diff changeset
1520 generate_v1_protocols (void)
kono
parents:
diff changeset
1521 {
kono
parents:
diff changeset
1522 tree p;
kono
parents:
diff changeset
1523
kono
parents:
diff changeset
1524 /* If a protocol was directly referenced, pull in indirect references. */
kono
parents:
diff changeset
1525 for (p = protocol_chain; p; p = TREE_CHAIN (p))
kono
parents:
diff changeset
1526 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
kono
parents:
diff changeset
1527 generate_protocol_references (PROTOCOL_LIST (p));
kono
parents:
diff changeset
1528
kono
parents:
diff changeset
1529 for (p = protocol_chain; p; p = TREE_CHAIN (p))
kono
parents:
diff changeset
1530 {
kono
parents:
diff changeset
1531 tree decl, encoding, initlist, protocol_name_expr;
kono
parents:
diff changeset
1532 tree refs_type, refs_decl, refs_expr;
kono
parents:
diff changeset
1533 location_t loc;
kono
parents:
diff changeset
1534 tree nst_methods = PROTOCOL_NST_METHODS (p);
kono
parents:
diff changeset
1535 tree cls_methods = PROTOCOL_CLS_METHODS (p);
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 /* If protocol wasn't referenced, don't generate any code. */
kono
parents:
diff changeset
1538 decl = PROTOCOL_FORWARD_DECL (p);
kono
parents:
diff changeset
1539
kono
parents:
diff changeset
1540 if (!decl)
kono
parents:
diff changeset
1541 continue;
kono
parents:
diff changeset
1542
kono
parents:
diff changeset
1543 /* Make sure we link in the Protocol class. */
kono
parents:
diff changeset
1544 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
kono
parents:
diff changeset
1545
kono
parents:
diff changeset
1546 while (nst_methods)
kono
parents:
diff changeset
1547 {
kono
parents:
diff changeset
1548 if (! METHOD_ENCODING (nst_methods))
kono
parents:
diff changeset
1549 {
kono
parents:
diff changeset
1550 encoding = encode_method_prototype (nst_methods);
kono
parents:
diff changeset
1551 METHOD_ENCODING (nst_methods) = encoding;
kono
parents:
diff changeset
1552 }
kono
parents:
diff changeset
1553 nst_methods = TREE_CHAIN (nst_methods);
kono
parents:
diff changeset
1554 }
kono
parents:
diff changeset
1555
kono
parents:
diff changeset
1556 UOBJC_INSTANCE_METHODS_decl =
kono
parents:
diff changeset
1557 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
kono
parents:
diff changeset
1558 "_OBJC_ProtocolInstanceMethods",
kono
parents:
diff changeset
1559 meta_proto_nst_meth);
kono
parents:
diff changeset
1560
kono
parents:
diff changeset
1561 while (cls_methods)
kono
parents:
diff changeset
1562 {
kono
parents:
diff changeset
1563 if (! METHOD_ENCODING (cls_methods))
kono
parents:
diff changeset
1564 {
kono
parents:
diff changeset
1565 encoding = encode_method_prototype (cls_methods);
kono
parents:
diff changeset
1566 METHOD_ENCODING (cls_methods) = encoding;
kono
parents:
diff changeset
1567 }
kono
parents:
diff changeset
1568
kono
parents:
diff changeset
1569 cls_methods = TREE_CHAIN (cls_methods);
kono
parents:
diff changeset
1570 }
kono
parents:
diff changeset
1571
kono
parents:
diff changeset
1572 UOBJC_CLASS_METHODS_decl =
kono
parents:
diff changeset
1573 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
kono
parents:
diff changeset
1574 "_OBJC_ProtocolClassMethods",
kono
parents:
diff changeset
1575 meta_proto_cls_meth);
kono
parents:
diff changeset
1576
kono
parents:
diff changeset
1577 /* There should be no optional methods for ABI-0 - but we need to
kono
parents:
diff changeset
1578 check all this here before the lists are made. */
kono
parents:
diff changeset
1579 nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
kono
parents:
diff changeset
1580 while (nst_methods)
kono
parents:
diff changeset
1581 {
kono
parents:
diff changeset
1582 if (! METHOD_ENCODING (nst_methods))
kono
parents:
diff changeset
1583 {
kono
parents:
diff changeset
1584 encoding = encode_method_prototype (nst_methods);
kono
parents:
diff changeset
1585 METHOD_ENCODING (nst_methods) = encoding;
kono
parents:
diff changeset
1586 }
kono
parents:
diff changeset
1587 nst_methods = TREE_CHAIN (nst_methods);
kono
parents:
diff changeset
1588 }
kono
parents:
diff changeset
1589
kono
parents:
diff changeset
1590 V1_Protocol_OPT_NST_METHODS_decl =
kono
parents:
diff changeset
1591 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
kono
parents:
diff changeset
1592 "_OBJC_OptionalProtocolInstanceMethods",
kono
parents:
diff changeset
1593 meta_proto_nst_meth);
kono
parents:
diff changeset
1594
kono
parents:
diff changeset
1595 cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
kono
parents:
diff changeset
1596 while (cls_methods)
kono
parents:
diff changeset
1597 {
kono
parents:
diff changeset
1598 if (! METHOD_ENCODING (cls_methods))
kono
parents:
diff changeset
1599 {
kono
parents:
diff changeset
1600 encoding = encode_method_prototype (cls_methods);
kono
parents:
diff changeset
1601 METHOD_ENCODING (cls_methods) = encoding;
kono
parents:
diff changeset
1602 }
kono
parents:
diff changeset
1603
kono
parents:
diff changeset
1604 cls_methods = TREE_CHAIN (cls_methods);
kono
parents:
diff changeset
1605 }
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 V1_Protocol_OPT_CLS_METHODS_decl =
kono
parents:
diff changeset
1608 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
kono
parents:
diff changeset
1609 "_OBJC_OptionalProtocolClassMethods",
kono
parents:
diff changeset
1610 meta_proto_cls_meth);
kono
parents:
diff changeset
1611
kono
parents:
diff changeset
1612 if (PROTOCOL_LIST (p))
kono
parents:
diff changeset
1613 refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
kono
parents:
diff changeset
1614 else
kono
parents:
diff changeset
1615 refs_decl = 0;
kono
parents:
diff changeset
1616
kono
parents:
diff changeset
1617 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
kono
parents:
diff changeset
1618 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
kono
parents:
diff changeset
1619 /* TODO: more locations to be fixed up... */
kono
parents:
diff changeset
1620 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
1621 refs_type =
kono
parents:
diff changeset
1622 build_pointer_type (build_pointer_type (objc_protocol_template));
kono
parents:
diff changeset
1623 if (refs_decl)
kono
parents:
diff changeset
1624 refs_expr = convert (refs_type,
kono
parents:
diff changeset
1625 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
kono
parents:
diff changeset
1626 else
kono
parents:
diff changeset
1627 refs_expr = convert (refs_type, null_pointer_node);
kono
parents:
diff changeset
1628
kono
parents:
diff changeset
1629 if (flag_objc_abi < 1)
kono
parents:
diff changeset
1630 {
kono
parents:
diff changeset
1631 /* Original ABI. */
kono
parents:
diff changeset
1632 initlist =
kono
parents:
diff changeset
1633 build_protocol_initializer (TREE_TYPE (decl),
kono
parents:
diff changeset
1634 protocol_name_expr, refs_expr,
kono
parents:
diff changeset
1635 UOBJC_INSTANCE_METHODS_decl,
kono
parents:
diff changeset
1636 UOBJC_CLASS_METHODS_decl);
kono
parents:
diff changeset
1637 finish_var_decl (decl, initlist);
kono
parents:
diff changeset
1638 continue;
kono
parents:
diff changeset
1639 }
kono
parents:
diff changeset
1640
kono
parents:
diff changeset
1641 /* else - V1 extensions. */
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 V1_Property_decl =
kono
parents:
diff changeset
1644 generate_v1_property_table (p, NULL_TREE);
kono
parents:
diff changeset
1645
kono
parents:
diff changeset
1646 V1_ProtocolExt_decl =
kono
parents:
diff changeset
1647 generate_v1_objc_protocol_extension (p,
kono
parents:
diff changeset
1648 V1_Protocol_OPT_NST_METHODS_decl,
kono
parents:
diff changeset
1649 V1_Protocol_OPT_CLS_METHODS_decl,
kono
parents:
diff changeset
1650 V1_Property_decl);
kono
parents:
diff changeset
1651
kono
parents:
diff changeset
1652 initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
kono
parents:
diff changeset
1653 protocol_name_expr, refs_expr,
kono
parents:
diff changeset
1654 UOBJC_INSTANCE_METHODS_decl,
kono
parents:
diff changeset
1655 UOBJC_CLASS_METHODS_decl,
kono
parents:
diff changeset
1656 V1_ProtocolExt_decl);
kono
parents:
diff changeset
1657 finish_var_decl (decl, initlist);
kono
parents:
diff changeset
1658 }
kono
parents:
diff changeset
1659 }
kono
parents:
diff changeset
1660
kono
parents:
diff changeset
1661 static tree
kono
parents:
diff changeset
1662 generate_dispatch_table (tree chain, const char *name, tree attr)
kono
parents:
diff changeset
1663 {
kono
parents:
diff changeset
1664 tree decl, method_list_template, initlist;
kono
parents:
diff changeset
1665 vec<constructor_elt, va_gc> *v = NULL;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1666 int size;
111
kono
parents:
diff changeset
1667
kono
parents:
diff changeset
1668 if (!chain || !name || !(size = list_length (chain)))
kono
parents:
diff changeset
1669 return NULL_TREE;
kono
parents:
diff changeset
1670
kono
parents:
diff changeset
1671 if (!objc_method_template)
kono
parents:
diff changeset
1672 objc_method_template = build_method_template ();
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 method_list_template = build_method_list_template (objc_method_template,
kono
parents:
diff changeset
1675 size);
kono
parents:
diff changeset
1676 initlist = build_dispatch_table_initializer (objc_method_template, chain);
kono
parents:
diff changeset
1677
kono
parents:
diff changeset
1678 decl = start_var_decl (method_list_template, name);
kono
parents:
diff changeset
1679
kono
parents:
diff changeset
1680 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
kono
parents:
diff changeset
1681 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
1682 build_int_cst (integer_type_node, size));
kono
parents:
diff changeset
1683 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
kono
parents:
diff changeset
1684
kono
parents:
diff changeset
1685 OBJCMETA (decl, objc_meta, attr);
kono
parents:
diff changeset
1686 finish_var_decl (decl,
kono
parents:
diff changeset
1687 objc_build_constructor (TREE_TYPE (decl), v));
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689 return decl;
kono
parents:
diff changeset
1690 }
kono
parents:
diff changeset
1691
kono
parents:
diff changeset
1692 /* Init a category. */
kono
parents:
diff changeset
1693 static tree
kono
parents:
diff changeset
1694 build_v1_category_initializer (tree type, tree cat_name, tree class_name,
kono
parents:
diff changeset
1695 tree inst_methods, tree class_methods,
kono
parents:
diff changeset
1696 tree protocol_list, tree property_list,
kono
parents:
diff changeset
1697 location_t loc)
kono
parents:
diff changeset
1698 {
kono
parents:
diff changeset
1699 tree expr, ltyp;
kono
parents:
diff changeset
1700 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
kono
parents:
diff changeset
1703 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
kono
parents:
diff changeset
1704
kono
parents:
diff changeset
1705 ltyp = objc_method_list_ptr;
kono
parents:
diff changeset
1706 if (inst_methods)
kono
parents:
diff changeset
1707 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
kono
parents:
diff changeset
1708 else
kono
parents:
diff changeset
1709 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1710 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 if (class_methods)
kono
parents:
diff changeset
1713 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
kono
parents:
diff changeset
1714 else
kono
parents:
diff changeset
1715 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1716 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1717
kono
parents:
diff changeset
1718 /* protocol_list = */
kono
parents:
diff changeset
1719 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
kono
parents:
diff changeset
1720 if (protocol_list)
kono
parents:
diff changeset
1721 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
kono
parents:
diff changeset
1722 else
kono
parents:
diff changeset
1723 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1724 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1725
kono
parents:
diff changeset
1726 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
1727 {
kono
parents:
diff changeset
1728 int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
kono
parents:
diff changeset
1729 expr = build_int_cst (NULL_TREE, val);
kono
parents:
diff changeset
1730 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1731 ltyp = objc_prop_list_ptr;
kono
parents:
diff changeset
1732 if (property_list)
kono
parents:
diff changeset
1733 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
kono
parents:
diff changeset
1734 else
kono
parents:
diff changeset
1735 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1736 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1737 }
kono
parents:
diff changeset
1738
kono
parents:
diff changeset
1739 return objc_build_constructor (type, v);
kono
parents:
diff changeset
1740 }
kono
parents:
diff changeset
1741
kono
parents:
diff changeset
1742 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
kono
parents:
diff changeset
1743 /* TODO: get rid of passing stuff around in globals. */
kono
parents:
diff changeset
1744 static void
kono
parents:
diff changeset
1745 generate_v1_category (struct imp_entry *impent)
kono
parents:
diff changeset
1746 {
kono
parents:
diff changeset
1747 tree initlist, cat_name_expr, class_name_expr;
kono
parents:
diff changeset
1748 tree protocol_decl, category, cat_decl;
kono
parents:
diff changeset
1749 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
kono
parents:
diff changeset
1750 tree cat = impent->imp_context;
kono
parents:
diff changeset
1751 location_t loc;
kono
parents:
diff changeset
1752 char buf[BUFSIZE];
kono
parents:
diff changeset
1753
kono
parents:
diff changeset
1754 cat_decl = impent->class_decl;
kono
parents:
diff changeset
1755 loc = DECL_SOURCE_LOCATION (cat_decl);
kono
parents:
diff changeset
1756
kono
parents:
diff changeset
1757 add_class_reference (CLASS_NAME (cat));
kono
parents:
diff changeset
1758 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
kono
parents:
diff changeset
1759 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
kono
parents:
diff changeset
1760
kono
parents:
diff changeset
1761 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 if (category && CLASS_PROTOCOL_LIST (category))
kono
parents:
diff changeset
1764 {
kono
parents:
diff changeset
1765 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
kono
parents:
diff changeset
1766 protocol_decl = generate_v1_protocol_list (category, cat);
kono
parents:
diff changeset
1767 }
kono
parents:
diff changeset
1768 else
kono
parents:
diff changeset
1769 protocol_decl = 0;
kono
parents:
diff changeset
1770
kono
parents:
diff changeset
1771 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
1772 V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
kono
parents:
diff changeset
1773 else
kono
parents:
diff changeset
1774 V1_Property_decl = NULL_TREE;
kono
parents:
diff changeset
1775
kono
parents:
diff changeset
1776 if (CLASS_NST_METHODS (cat))
kono
parents:
diff changeset
1777 {
kono
parents:
diff changeset
1778 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
kono
parents:
diff changeset
1779 IDENTIFIER_POINTER (CLASS_NAME (cat)),
kono
parents:
diff changeset
1780 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
kono
parents:
diff changeset
1781 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
kono
parents:
diff changeset
1782 meta_cati_meth);
kono
parents:
diff changeset
1783 }
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 if (CLASS_CLS_METHODS (cat))
kono
parents:
diff changeset
1786 {
kono
parents:
diff changeset
1787 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
kono
parents:
diff changeset
1788 IDENTIFIER_POINTER (CLASS_NAME (cat)),
kono
parents:
diff changeset
1789 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
kono
parents:
diff changeset
1790 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
kono
parents:
diff changeset
1791 meta_catc_meth);
kono
parents:
diff changeset
1792 }
kono
parents:
diff changeset
1793
kono
parents:
diff changeset
1794 initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
kono
parents:
diff changeset
1795 cat_name_expr, class_name_expr,
kono
parents:
diff changeset
1796 inst_methods, class_methods,
kono
parents:
diff changeset
1797 protocol_decl, V1_Property_decl,
kono
parents:
diff changeset
1798 loc);
kono
parents:
diff changeset
1799
kono
parents:
diff changeset
1800 finish_var_decl (cat_decl, initlist);
kono
parents:
diff changeset
1801 impent->class_decl = cat_decl;
kono
parents:
diff changeset
1802 }
kono
parents:
diff changeset
1803
kono
parents:
diff changeset
1804 /* This routine builds the class extension used by v1 NeXT. */
kono
parents:
diff changeset
1805
kono
parents:
diff changeset
1806 static tree
kono
parents:
diff changeset
1807 generate_objc_class_ext (tree property_list, tree context)
kono
parents:
diff changeset
1808 {
kono
parents:
diff changeset
1809 tree decl, expr, ltyp;
kono
parents:
diff changeset
1810 tree weak_ivar_layout_tree;
kono
parents:
diff changeset
1811 int size;
kono
parents:
diff changeset
1812 location_t loc;
kono
parents:
diff changeset
1813 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1814 char buf[BUFSIZE];
kono
parents:
diff changeset
1815
kono
parents:
diff changeset
1816 /* TODO: pass the loc in or find it from args. */
kono
parents:
diff changeset
1817 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 /* const char *weak_ivar_layout
kono
parents:
diff changeset
1820 TODO: Figure the ivar layouts out... */
kono
parents:
diff changeset
1821 weak_ivar_layout_tree = NULL_TREE;
kono
parents:
diff changeset
1822
kono
parents:
diff changeset
1823 if (!property_list && !weak_ivar_layout_tree)
kono
parents:
diff changeset
1824 return NULL_TREE;
kono
parents:
diff changeset
1825
kono
parents:
diff changeset
1826 if (!objc_class_ext_template)
kono
parents:
diff changeset
1827 build_objc_class_ext_template ();
kono
parents:
diff changeset
1828
kono
parents:
diff changeset
1829 /* uint32_t size */
kono
parents:
diff changeset
1830 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
kono
parents:
diff changeset
1831 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
kono
parents:
diff changeset
1832
kono
parents:
diff changeset
1833 ltyp = const_string_type_node;
kono
parents:
diff changeset
1834 if (weak_ivar_layout_tree)
kono
parents:
diff changeset
1835 expr = convert (ltyp, weak_ivar_layout_tree);
kono
parents:
diff changeset
1836 else
kono
parents:
diff changeset
1837 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1838 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1839
kono
parents:
diff changeset
1840 /* struct _prop_list_t *properties; */
kono
parents:
diff changeset
1841 ltyp = objc_prop_list_ptr;
kono
parents:
diff changeset
1842 if (property_list)
kono
parents:
diff changeset
1843 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
kono
parents:
diff changeset
1844 else
kono
parents:
diff changeset
1845 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1846 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
kono
parents:
diff changeset
1849 IDENTIFIER_POINTER (CLASS_NAME (context)));
kono
parents:
diff changeset
1850 decl = start_var_decl (objc_class_ext_template, buf);
kono
parents:
diff changeset
1851 expr = objc_build_constructor (TREE_TYPE (decl), v);
kono
parents:
diff changeset
1852 OBJCMETA (decl, objc_meta, meta_class_extension);
kono
parents:
diff changeset
1853 finish_var_decl (decl, expr);
kono
parents:
diff changeset
1854 return decl;
kono
parents:
diff changeset
1855 }
kono
parents:
diff changeset
1856
kono
parents:
diff changeset
1857 /* struct _objc_class {
kono
parents:
diff changeset
1858 struct objc_class *isa;
kono
parents:
diff changeset
1859 struct objc_class *super_class;
kono
parents:
diff changeset
1860 char *name;
kono
parents:
diff changeset
1861 long version;
kono
parents:
diff changeset
1862 long info;
kono
parents:
diff changeset
1863 long instance_size;
kono
parents:
diff changeset
1864 struct objc_ivar_list *ivars;
kono
parents:
diff changeset
1865 struct objc_method_list *methods;
kono
parents:
diff changeset
1866 struct objc_cache *cache;
kono
parents:
diff changeset
1867 struct objc_protocol_list *protocols;
kono
parents:
diff changeset
1868 #if ABI >= 1
kono
parents:
diff changeset
1869 const char *ivar_layout;
kono
parents:
diff changeset
1870 struct _objc_class_ext *ext;
kono
parents:
diff changeset
1871 #else
kono
parents:
diff changeset
1872 void *sel_id;
kono
parents:
diff changeset
1873 void *gc_object_type;
kono
parents:
diff changeset
1874 #endif
kono
parents:
diff changeset
1875 }; */
kono
parents:
diff changeset
1876
kono
parents:
diff changeset
1877 static tree
kono
parents:
diff changeset
1878 build_v1_shared_structure_initializer (tree type, tree isa, tree super,
kono
parents:
diff changeset
1879 tree name, tree size, int status,
kono
parents:
diff changeset
1880 tree dispatch_table, tree ivar_list,
kono
parents:
diff changeset
1881 tree protocol_list, tree class_ext)
kono
parents:
diff changeset
1882 {
kono
parents:
diff changeset
1883 tree expr, ltyp;
kono
parents:
diff changeset
1884 location_t loc;
kono
parents:
diff changeset
1885 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
1886
kono
parents:
diff changeset
1887 /* TODO: fish the location out of the input data. */
kono
parents:
diff changeset
1888 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
1889
kono
parents:
diff changeset
1890 /* isa = */
kono
parents:
diff changeset
1891 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
kono
parents:
diff changeset
1892
kono
parents:
diff changeset
1893 /* super_class = */
kono
parents:
diff changeset
1894 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
kono
parents:
diff changeset
1895
kono
parents:
diff changeset
1896 /* name = */
kono
parents:
diff changeset
1897 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
kono
parents:
diff changeset
1898
kono
parents:
diff changeset
1899 /* version = */
kono
parents:
diff changeset
1900 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
1901 build_int_cst (long_integer_type_node, 0));
kono
parents:
diff changeset
1902
kono
parents:
diff changeset
1903 /* info = */
kono
parents:
diff changeset
1904 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
1905 build_int_cst (long_integer_type_node, status));
kono
parents:
diff changeset
1906
kono
parents:
diff changeset
1907 /* instance_size = */
kono
parents:
diff changeset
1908 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
1909 convert (long_integer_type_node, size));
kono
parents:
diff changeset
1910
kono
parents:
diff changeset
1911 /* objc_ivar_list = */
kono
parents:
diff changeset
1912 ltyp = objc_ivar_list_ptr;
kono
parents:
diff changeset
1913 if (ivar_list)
kono
parents:
diff changeset
1914 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
kono
parents:
diff changeset
1915 else
kono
parents:
diff changeset
1916 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1917 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1918
kono
parents:
diff changeset
1919 /* objc_method_list = */
kono
parents:
diff changeset
1920 ltyp = objc_method_list_ptr;
kono
parents:
diff changeset
1921 if (dispatch_table)
kono
parents:
diff changeset
1922 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
kono
parents:
diff changeset
1923 else
kono
parents:
diff changeset
1924 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1925 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1926
kono
parents:
diff changeset
1927 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
1928 get_identifier ("objc_cache")));
kono
parents:
diff changeset
1929 /* method_cache = */
kono
parents:
diff changeset
1930 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
kono
parents:
diff changeset
1931
kono
parents:
diff changeset
1932 /* protocol_list = */
kono
parents:
diff changeset
1933 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
kono
parents:
diff changeset
1934 if (protocol_list)
kono
parents:
diff changeset
1935 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
kono
parents:
diff changeset
1936 else
kono
parents:
diff changeset
1937 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1938 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1939
kono
parents:
diff changeset
1940 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
1941 {
kono
parents:
diff changeset
1942 /* TODO: figure out the ivar_layout stuff. */
kono
parents:
diff changeset
1943 expr = convert (const_string_type_node, null_pointer_node);
kono
parents:
diff changeset
1944 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1945 if (!objc_class_ext_template)
kono
parents:
diff changeset
1946 build_objc_class_ext_template ();
kono
parents:
diff changeset
1947 ltyp = build_pointer_type (objc_class_ext_template);
kono
parents:
diff changeset
1948 if (class_ext)
kono
parents:
diff changeset
1949 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
kono
parents:
diff changeset
1950 else
kono
parents:
diff changeset
1951 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
1952 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
1953 }
kono
parents:
diff changeset
1954 else
kono
parents:
diff changeset
1955 {
kono
parents:
diff changeset
1956 /* sel_id = NULL */
kono
parents:
diff changeset
1957 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
kono
parents:
diff changeset
1958
kono
parents:
diff changeset
1959 /* gc_object_type = NULL */
kono
parents:
diff changeset
1960 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
kono
parents:
diff changeset
1961 }
kono
parents:
diff changeset
1962 return objc_build_constructor (type, v);
kono
parents:
diff changeset
1963 }
kono
parents:
diff changeset
1964
kono
parents:
diff changeset
1965 static tree
kono
parents:
diff changeset
1966 generate_ivars_list (tree chain, const char *name, tree attr)
kono
parents:
diff changeset
1967 {
kono
parents:
diff changeset
1968 tree initlist, ivar_list_template, decl;
kono
parents:
diff changeset
1969 int size;
kono
parents:
diff changeset
1970 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
1971
kono
parents:
diff changeset
1972 if (!chain)
kono
parents:
diff changeset
1973 return NULL_TREE;
kono
parents:
diff changeset
1974
kono
parents:
diff changeset
1975 if (!objc_ivar_template)
kono
parents:
diff changeset
1976 objc_ivar_template = build_ivar_template ();
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 size = ivar_list_length (chain);
kono
parents:
diff changeset
1979
kono
parents:
diff changeset
1980 generating_instance_variables = 1;
kono
parents:
diff changeset
1981 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
kono
parents:
diff changeset
1982 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
kono
parents:
diff changeset
1983 generating_instance_variables = 0;
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 decl = start_var_decl (ivar_list_template, name);
kono
parents:
diff changeset
1986
kono
parents:
diff changeset
1987 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
kono
parents:
diff changeset
1988 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
kono
parents:
diff changeset
1989
kono
parents:
diff changeset
1990 OBJCMETA (decl, objc_meta, attr);
kono
parents:
diff changeset
1991 finish_var_decl (decl,
kono
parents:
diff changeset
1992 objc_build_constructor (TREE_TYPE (decl), inits));
kono
parents:
diff changeset
1993
kono
parents:
diff changeset
1994 return decl;
kono
parents:
diff changeset
1995 }
kono
parents:
diff changeset
1996
kono
parents:
diff changeset
1997 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
kono
parents:
diff changeset
1998 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 static void
kono
parents:
diff changeset
2001 generate_v1_class_structs (struct imp_entry *impent)
kono
parents:
diff changeset
2002 {
kono
parents:
diff changeset
2003 tree name_expr, super_expr, root_expr, class_decl, meta_decl;
kono
parents:
diff changeset
2004 tree my_root_id, my_super_id;
kono
parents:
diff changeset
2005 tree cast_type, initlist, protocol_decl;
kono
parents:
diff changeset
2006 tree class_ext_decl = NULL_TREE, props = NULL_TREE;
kono
parents:
diff changeset
2007 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
kono
parents:
diff changeset
2008 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
kono
parents:
diff changeset
2009 int cls_flags;
kono
parents:
diff changeset
2010 location_t loc;
kono
parents:
diff changeset
2011 char buf[BUFSIZE];
kono
parents:
diff changeset
2012
kono
parents:
diff changeset
2013 /* objc_implementation_context = impent->imp_context;
kono
parents:
diff changeset
2014 implementation_template = impent->imp_template;*/
kono
parents:
diff changeset
2015 class_decl = impent->class_decl;
kono
parents:
diff changeset
2016 meta_decl = impent->meta_decl;
kono
parents:
diff changeset
2017 cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
kono
parents:
diff changeset
2018
kono
parents:
diff changeset
2019 loc = DECL_SOURCE_LOCATION (impent->class_decl);
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 if (flag_objc_abi >= 1)
kono
parents:
diff changeset
2022 {
kono
parents:
diff changeset
2023 /* ABI=1 additions. */
kono
parents:
diff changeset
2024 props = generate_v1_property_table (NULL_TREE, impent->imp_context);
kono
parents:
diff changeset
2025 class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
kono
parents:
diff changeset
2026 }
kono
parents:
diff changeset
2027
kono
parents:
diff changeset
2028 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
kono
parents:
diff changeset
2029 if (my_super_id)
kono
parents:
diff changeset
2030 {
kono
parents:
diff changeset
2031 add_class_reference (my_super_id);
kono
parents:
diff changeset
2032
kono
parents:
diff changeset
2033 /* Compute "my_root_id" - this is required for code generation.
kono
parents:
diff changeset
2034 the "isa" for all meta class structures points to the root of
kono
parents:
diff changeset
2035 the inheritance hierarchy (e.g. "__Object")... */
kono
parents:
diff changeset
2036 my_root_id = my_super_id;
kono
parents:
diff changeset
2037 do
kono
parents:
diff changeset
2038 {
kono
parents:
diff changeset
2039 tree my_root_int = lookup_interface (my_root_id);
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
kono
parents:
diff changeset
2042 my_root_id = CLASS_SUPER_NAME (my_root_int);
kono
parents:
diff changeset
2043 else
kono
parents:
diff changeset
2044 break;
kono
parents:
diff changeset
2045 }
kono
parents:
diff changeset
2046 while (1);
kono
parents:
diff changeset
2047 super_expr = add_objc_string (my_super_id, class_names);
kono
parents:
diff changeset
2048 }
kono
parents:
diff changeset
2049 else
kono
parents:
diff changeset
2050 {
kono
parents:
diff changeset
2051 /* No super class. */
kono
parents:
diff changeset
2052 my_root_id = CLASS_NAME (impent->imp_template);
kono
parents:
diff changeset
2053 super_expr = null_pointer_node;
kono
parents:
diff changeset
2054 }
kono
parents:
diff changeset
2055
kono
parents:
diff changeset
2056 /* Install class `isa' and `super' pointers at runtime. */
kono
parents:
diff changeset
2057 cast_type = build_pointer_type (objc_class_template);
kono
parents:
diff changeset
2058 super_expr = build_c_cast (loc, cast_type, super_expr);
kono
parents:
diff changeset
2059
kono
parents:
diff changeset
2060 root_expr = add_objc_string (my_root_id, class_names);
kono
parents:
diff changeset
2061 root_expr = build_c_cast (loc, cast_type, root_expr);
kono
parents:
diff changeset
2062
kono
parents:
diff changeset
2063 if (CLASS_PROTOCOL_LIST (impent->imp_template))
kono
parents:
diff changeset
2064 {
kono
parents:
diff changeset
2065 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
kono
parents:
diff changeset
2066 protocol_decl = generate_v1_protocol_list (impent->imp_template,
kono
parents:
diff changeset
2067 impent->imp_context);
kono
parents:
diff changeset
2068 }
kono
parents:
diff changeset
2069 else
kono
parents:
diff changeset
2070 protocol_decl = NULL_TREE;
kono
parents:
diff changeset
2071
kono
parents:
diff changeset
2072 if (CLASS_CLS_METHODS (impent->imp_context))
kono
parents:
diff changeset
2073 {
kono
parents:
diff changeset
2074 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
kono
parents:
diff changeset
2075 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
kono
parents:
diff changeset
2076 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
kono
parents:
diff changeset
2077 buf, meta_clac_meth);
kono
parents:
diff changeset
2078 }
kono
parents:
diff changeset
2079
kono
parents:
diff changeset
2080 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
kono
parents:
diff changeset
2081 && (chain = TYPE_FIELDS (objc_class_template)))
kono
parents:
diff changeset
2082 {
kono
parents:
diff changeset
2083 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
kono
parents:
diff changeset
2084 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
kono
parents:
diff changeset
2085 class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
kono
parents:
diff changeset
2086 }
kono
parents:
diff changeset
2087 /* TODO: get rid of hidden passing of stuff in globals. */
kono
parents:
diff changeset
2088 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
kono
parents:
diff changeset
2089
kono
parents:
diff changeset
2090 name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
kono
parents:
diff changeset
2091
kono
parents:
diff changeset
2092 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
kono
parents:
diff changeset
2093
kono
parents:
diff changeset
2094 initlist = build_v1_shared_structure_initializer
kono
parents:
diff changeset
2095 (TREE_TYPE (meta_decl),
kono
parents:
diff changeset
2096 root_expr, super_expr, name_expr,
kono
parents:
diff changeset
2097 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
kono
parents:
diff changeset
2098 CLS_META, class_methods, class_ivars,
kono
parents:
diff changeset
2099 protocol_decl, NULL_TREE);
kono
parents:
diff changeset
2100
kono
parents:
diff changeset
2101 finish_var_decl (meta_decl, initlist);
kono
parents:
diff changeset
2102 impent->meta_decl = meta_decl;
kono
parents:
diff changeset
2103
kono
parents:
diff changeset
2104 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
kono
parents:
diff changeset
2105 if (CLASS_NST_METHODS (impent->imp_context))
kono
parents:
diff changeset
2106 {
kono
parents:
diff changeset
2107 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
kono
parents:
diff changeset
2108 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
kono
parents:
diff changeset
2109 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
kono
parents:
diff changeset
2110 buf, meta_clai_meth);
kono
parents:
diff changeset
2111 }
kono
parents:
diff changeset
2112
kono
parents:
diff changeset
2113 if ((chain = CLASS_IVARS (impent->imp_template)))
kono
parents:
diff changeset
2114 {
kono
parents:
diff changeset
2115 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
kono
parents:
diff changeset
2116 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
kono
parents:
diff changeset
2117 inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
kono
parents:
diff changeset
2118 }
kono
parents:
diff changeset
2119
kono
parents:
diff changeset
2120 initlist = build_v1_shared_structure_initializer
kono
parents:
diff changeset
2121 (TREE_TYPE (class_decl),
kono
parents:
diff changeset
2122 build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
kono
parents:
diff changeset
2123 super_expr, name_expr,
kono
parents:
diff changeset
2124 convert (integer_type_node,
kono
parents:
diff changeset
2125 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
kono
parents:
diff changeset
2126 CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
kono
parents:
diff changeset
2127 protocol_decl, class_ext_decl);
kono
parents:
diff changeset
2128
kono
parents:
diff changeset
2129 finish_var_decl (class_decl, initlist);
kono
parents:
diff changeset
2130 impent->class_decl = class_decl;
kono
parents:
diff changeset
2131 }
kono
parents:
diff changeset
2132
kono
parents:
diff changeset
2133 /* --- Output NeXT V1 Metadata --- */
kono
parents:
diff changeset
2134
kono
parents:
diff changeset
2135 /* Create the initial value for the `defs' field of _objc_symtab.
kono
parents:
diff changeset
2136 This is a CONSTRUCTOR. */
kono
parents:
diff changeset
2137
kono
parents:
diff changeset
2138 static tree
kono
parents:
diff changeset
2139 init_def_list (tree type)
kono
parents:
diff changeset
2140 {
kono
parents:
diff changeset
2141 tree expr;
kono
parents:
diff changeset
2142 location_t loc;
kono
parents:
diff changeset
2143 struct imp_entry *impent;
kono
parents:
diff changeset
2144 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
2145
kono
parents:
diff changeset
2146 if (imp_count)
kono
parents:
diff changeset
2147 for (impent = imp_list; impent; impent = impent->next)
kono
parents:
diff changeset
2148 {
kono
parents:
diff changeset
2149 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
kono
parents:
diff changeset
2150 {
kono
parents:
diff changeset
2151 loc = DECL_SOURCE_LOCATION (impent->class_decl);
kono
parents:
diff changeset
2152 expr = build_unary_op (loc,
kono
parents:
diff changeset
2153 ADDR_EXPR, impent->class_decl, 0);
kono
parents:
diff changeset
2154 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
2155 }
kono
parents:
diff changeset
2156 }
kono
parents:
diff changeset
2157
kono
parents:
diff changeset
2158 if (cat_count)
kono
parents:
diff changeset
2159 for (impent = imp_list; impent; impent = impent->next)
kono
parents:
diff changeset
2160 {
kono
parents:
diff changeset
2161 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
kono
parents:
diff changeset
2162 {
kono
parents:
diff changeset
2163 loc = DECL_SOURCE_LOCATION (impent->class_decl);
kono
parents:
diff changeset
2164 expr = build_unary_op (loc,
kono
parents:
diff changeset
2165 ADDR_EXPR, impent->class_decl, 0);
kono
parents:
diff changeset
2166 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
2167 }
kono
parents:
diff changeset
2168 }
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 return objc_build_constructor (type, v);
kono
parents:
diff changeset
2171 }
kono
parents:
diff changeset
2172
kono
parents:
diff changeset
2173 /* Take care of defining and initializing _OBJC_SYMBOLS. */
kono
parents:
diff changeset
2174
kono
parents:
diff changeset
2175 /* Predefine the following data type:
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 struct _objc_symtab
kono
parents:
diff changeset
2178 {
kono
parents:
diff changeset
2179 long sel_ref_cnt;
kono
parents:
diff changeset
2180 SEL *refs;
kono
parents:
diff changeset
2181 short cls_def_cnt;
kono
parents:
diff changeset
2182 short cat_def_cnt;
kono
parents:
diff changeset
2183 void *defs[cls_def_cnt + cat_def_cnt];
kono
parents:
diff changeset
2184 }; */
kono
parents:
diff changeset
2185
kono
parents:
diff changeset
2186 static void
kono
parents:
diff changeset
2187 build_objc_symtab_template (void)
kono
parents:
diff changeset
2188 {
kono
parents:
diff changeset
2189 tree fields, *chain = NULL;
kono
parents:
diff changeset
2190
kono
parents:
diff changeset
2191 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
kono
parents:
diff changeset
2192
kono
parents:
diff changeset
2193 /* long sel_ref_cnt; */
kono
parents:
diff changeset
2194 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
kono
parents:
diff changeset
2195
kono
parents:
diff changeset
2196 /* SEL *refs; */
kono
parents:
diff changeset
2197 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
kono
parents:
diff changeset
2198
kono
parents:
diff changeset
2199 /* short cls_def_cnt; */
kono
parents:
diff changeset
2200 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
kono
parents:
diff changeset
2201
kono
parents:
diff changeset
2202 /* short cat_def_cnt; */
kono
parents:
diff changeset
2203 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
kono
parents:
diff changeset
2204
kono
parents:
diff changeset
2205 if (imp_count || cat_count)
kono
parents:
diff changeset
2206 {
kono
parents:
diff changeset
2207 /* void *defs[imp_count + cat_count (+ 1)]; */
kono
parents:
diff changeset
2208 /* NB: The index is one less than the size of the array. */
kono
parents:
diff changeset
2209 int index = imp_count + cat_count;
kono
parents:
diff changeset
2210 tree array_type = build_sized_array_type (ptr_type_node, index);
kono
parents:
diff changeset
2211 add_field_decl (array_type, "defs", &chain);
kono
parents:
diff changeset
2212 }
kono
parents:
diff changeset
2213
kono
parents:
diff changeset
2214 objc_finish_struct (objc_symtab_template, fields);
kono
parents:
diff changeset
2215 }
kono
parents:
diff changeset
2216 /* Construct the initial value for all of _objc_symtab. */
kono
parents:
diff changeset
2217
kono
parents:
diff changeset
2218 static tree
kono
parents:
diff changeset
2219 init_objc_symtab (tree type)
kono
parents:
diff changeset
2220 {
kono
parents:
diff changeset
2221 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
2222
kono
parents:
diff changeset
2223 /* sel_ref_cnt = { ..., 5, ... } */
kono
parents:
diff changeset
2224
kono
parents:
diff changeset
2225 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
2226 build_int_cst (long_integer_type_node, 0));
kono
parents:
diff changeset
2227
kono
parents:
diff changeset
2228 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
kono
parents:
diff changeset
2229
kono
parents:
diff changeset
2230 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
2231 convert (build_pointer_type (objc_selector_type),
kono
parents:
diff changeset
2232 integer_zero_node));
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 /* cls_def_cnt = { ..., 5, ... } */
kono
parents:
diff changeset
2235
kono
parents:
diff changeset
2236 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
2237 build_int_cst (short_integer_type_node, imp_count));
kono
parents:
diff changeset
2238
kono
parents:
diff changeset
2239 /* cat_def_cnt = { ..., 5, ... } */
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
kono
parents:
diff changeset
2242 build_int_cst (short_integer_type_node, cat_count));
kono
parents:
diff changeset
2243
kono
parents:
diff changeset
2244 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
kono
parents:
diff changeset
2245
kono
parents:
diff changeset
2246 if (imp_count || cat_count)
kono
parents:
diff changeset
2247 {
kono
parents:
diff changeset
2248 tree field = TYPE_FIELDS (type);
kono
parents:
diff changeset
2249 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
kono
parents:
diff changeset
2252 }
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 return objc_build_constructor (type, v);
kono
parents:
diff changeset
2255 }
kono
parents:
diff changeset
2256
kono
parents:
diff changeset
2257 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
kono
parents:
diff changeset
2258 and initialized appropriately. */
kono
parents:
diff changeset
2259
kono
parents:
diff changeset
2260 static void
kono
parents:
diff changeset
2261 generate_objc_symtab_decl (void)
kono
parents:
diff changeset
2262 {
kono
parents:
diff changeset
2263 build_objc_symtab_template ();
kono
parents:
diff changeset
2264 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
kono
parents:
diff changeset
2265 /* Allow the runtime to mark meta-data such that it can be assigned to target
kono
parents:
diff changeset
2266 specific sections by the back-end. */
kono
parents:
diff changeset
2267 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
kono
parents:
diff changeset
2268 finish_var_decl (UOBJC_SYMBOLS_decl,
kono
parents:
diff changeset
2269 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
kono
parents:
diff changeset
2270 }
kono
parents:
diff changeset
2271
kono
parents:
diff changeset
2272 /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects
kono
parents:
diff changeset
2273 refer to, and define, symbols that enforce linkage of classes into the
kono
parents:
diff changeset
2274 executable image, preserving unix archive semantics.
kono
parents:
diff changeset
2275
kono
parents:
diff changeset
2276 At present (4.8), the only targets implementing this are Darwin; these
kono
parents:
diff changeset
2277 use top level asms to implement a scheme (see config/darwin-c.c). The
kono
parents:
diff changeset
2278 latter method is a hack, but compatible with LTO see also PR48109 for
kono
parents:
diff changeset
2279 further discussion and other possible methods. */
kono
parents:
diff changeset
2280
kono
parents:
diff changeset
2281 static void
kono
parents:
diff changeset
2282 handle_next_class_ref (tree chain ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2283 {
kono
parents:
diff changeset
2284 if (targetcm.objc_declare_unresolved_class_reference)
kono
parents:
diff changeset
2285 {
kono
parents:
diff changeset
2286 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
kono
parents:
diff changeset
2287 char *string = (char *) alloca (strlen (name) + 30);
kono
parents:
diff changeset
2288 sprintf (string, ".objc_class_name_%s", name);
kono
parents:
diff changeset
2289 targetcm.objc_declare_unresolved_class_reference (string);
kono
parents:
diff changeset
2290 }
kono
parents:
diff changeset
2291 }
kono
parents:
diff changeset
2292
kono
parents:
diff changeset
2293 static void
kono
parents:
diff changeset
2294 handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2295 {
kono
parents:
diff changeset
2296 if (targetcm.objc_declare_class_definition)
kono
parents:
diff changeset
2297 {
kono
parents:
diff changeset
2298 char buf[BUFSIZE];
kono
parents:
diff changeset
2299
kono
parents:
diff changeset
2300 switch (TREE_CODE (impent->imp_context))
kono
parents:
diff changeset
2301 {
kono
parents:
diff changeset
2302 case CLASS_IMPLEMENTATION_TYPE:
kono
parents:
diff changeset
2303 snprintf (buf, BUFSIZE, ".objc_class_name_%s",
kono
parents:
diff changeset
2304 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
kono
parents:
diff changeset
2305 break;
kono
parents:
diff changeset
2306 case CATEGORY_IMPLEMENTATION_TYPE:
kono
parents:
diff changeset
2307 snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
kono
parents:
diff changeset
2308 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
kono
parents:
diff changeset
2309 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
kono
parents:
diff changeset
2310 break;
kono
parents:
diff changeset
2311 default:
kono
parents:
diff changeset
2312 return;
kono
parents:
diff changeset
2313 }
kono
parents:
diff changeset
2314 targetcm.objc_declare_class_definition (buf);
kono
parents:
diff changeset
2315 }
kono
parents:
diff changeset
2316 }
kono
parents:
diff changeset
2317
kono
parents:
diff changeset
2318 static void
kono
parents:
diff changeset
2319 generate_classref_translation_entry (tree chain)
kono
parents:
diff changeset
2320 {
kono
parents:
diff changeset
2321 tree expr, decl, type;
kono
parents:
diff changeset
2322
kono
parents:
diff changeset
2323 decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
2324 type = TREE_TYPE (decl);
kono
parents:
diff changeset
2325
kono
parents:
diff changeset
2326 expr = add_objc_string (TREE_VALUE (chain), class_names);
kono
parents:
diff changeset
2327 expr = convert (type, expr); /* cast! */
kono
parents:
diff changeset
2328
kono
parents:
diff changeset
2329 /* This is a class reference. It is re-written by the runtime,
kono
parents:
diff changeset
2330 but will be optimized away unless we force it. */
kono
parents:
diff changeset
2331 DECL_PRESERVE_P (decl) = 1;
kono
parents:
diff changeset
2332 OBJCMETA (decl, objc_meta, meta_class_reference);
kono
parents:
diff changeset
2333 finish_var_decl (decl, expr);
kono
parents:
diff changeset
2334 return;
kono
parents:
diff changeset
2335 }
kono
parents:
diff changeset
2336
kono
parents:
diff changeset
2337 static void
kono
parents:
diff changeset
2338 objc_generate_v1_next_metadata (void)
kono
parents:
diff changeset
2339 {
kono
parents:
diff changeset
2340 struct imp_entry *impent;
kono
parents:
diff changeset
2341 tree chain, attr;
kono
parents:
diff changeset
2342 long vers;
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 /* FIXME: Make sure that we generate no metadata if there is nothing
kono
parents:
diff changeset
2345 to put into it. */
kono
parents:
diff changeset
2346
kono
parents:
diff changeset
2347 if (objc_static_instances)
kono
parents:
diff changeset
2348 gcc_unreachable (); /* Not for NeXT */
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 build_metadata_templates ();
kono
parents:
diff changeset
2351 objc_implementation_context =
kono
parents:
diff changeset
2352 implementation_template =
kono
parents:
diff changeset
2353 UOBJC_CLASS_decl =
kono
parents:
diff changeset
2354 UOBJC_METACLASS_decl = NULL_TREE;
kono
parents:
diff changeset
2355
kono
parents:
diff changeset
2356 for (impent = imp_list; impent; impent = impent->next)
kono
parents:
diff changeset
2357 {
kono
parents:
diff changeset
2358
kono
parents:
diff changeset
2359 /* If -gen-decls is present, Dump the @interface of each class.
kono
parents:
diff changeset
2360 TODO: Dump the classes in the order they were found, rather than in
kono
parents:
diff changeset
2361 reverse order as we are doing now. */
kono
parents:
diff changeset
2362 if (flag_gen_declaration)
kono
parents:
diff changeset
2363 dump_interface (gen_declaration_file, impent->imp_context);
kono
parents:
diff changeset
2364
kono
parents:
diff changeset
2365 /* all of the following reference the string pool... */
kono
parents:
diff changeset
2366 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
kono
parents:
diff changeset
2367 generate_v1_class_structs (impent);
kono
parents:
diff changeset
2368 else
kono
parents:
diff changeset
2369 generate_v1_category (impent);
kono
parents:
diff changeset
2370 }
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 /* If we are using an array of selectors, we must always
kono
parents:
diff changeset
2373 finish up the array decl even if no selectors were used. */
kono
parents:
diff changeset
2374 build_next_selector_translation_table ();
kono
parents:
diff changeset
2375
kono
parents:
diff changeset
2376 if (protocol_chain)
kono
parents:
diff changeset
2377 generate_v1_protocols ();
kono
parents:
diff changeset
2378
kono
parents:
diff changeset
2379 /* Pass summary information to the runtime. */
kono
parents:
diff changeset
2380 if (imp_count || cat_count)
kono
parents:
diff changeset
2381 generate_objc_symtab_decl ();
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 vers = OBJC_VERSION;
kono
parents:
diff changeset
2384 attr = build_tree_list (objc_meta, meta_modules);
kono
parents:
diff changeset
2385 build_module_descriptor (vers, attr);
kono
parents:
diff changeset
2386
kono
parents:
diff changeset
2387 /* Dump the class references. This forces the appropriate classes
kono
parents:
diff changeset
2388 to be linked into the executable image, preserving unix archive
kono
parents:
diff changeset
2389 semantics. */
kono
parents:
diff changeset
2390 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
2391 {
kono
parents:
diff changeset
2392 handle_next_class_ref (chain);
kono
parents:
diff changeset
2393 if (TREE_PURPOSE (chain))
kono
parents:
diff changeset
2394 generate_classref_translation_entry (chain);
kono
parents:
diff changeset
2395 }
kono
parents:
diff changeset
2396
kono
parents:
diff changeset
2397 for (impent = imp_list; impent; impent = impent->next)
kono
parents:
diff changeset
2398 handle_next_impent (impent);
kono
parents:
diff changeset
2399
kono
parents:
diff changeset
2400 /* Emit the strings tables. */
kono
parents:
diff changeset
2401 generate_strings ();
kono
parents:
diff changeset
2402 }
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 /* --- exceptions stuff --- */
kono
parents:
diff changeset
2405
kono
parents:
diff changeset
2406 /* Predefine the following data type:
kono
parents:
diff changeset
2407
kono
parents:
diff changeset
2408 struct _objc_exception_data
kono
parents:
diff changeset
2409 {
kono
parents:
diff changeset
2410 int buf[OBJC_JBLEN];
kono
parents:
diff changeset
2411 void *pointers[4];
kono
parents:
diff changeset
2412 }; */
kono
parents:
diff changeset
2413
kono
parents:
diff changeset
2414 /* The following yuckiness should prevent users from having to #include
kono
parents:
diff changeset
2415 <setjmp.h> in their code... */
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 /* Define to a harmless positive value so the below code doesn't die. */
kono
parents:
diff changeset
2418 #ifndef OBJC_JBLEN
kono
parents:
diff changeset
2419 #define OBJC_JBLEN 18
kono
parents:
diff changeset
2420 #endif
kono
parents:
diff changeset
2421
kono
parents:
diff changeset
2422 static void
kono
parents:
diff changeset
2423 build_next_objc_exception_stuff (void)
kono
parents:
diff changeset
2424 {
kono
parents:
diff changeset
2425 tree decls, temp_type, *chain = NULL;
kono
parents:
diff changeset
2426
kono
parents:
diff changeset
2427 objc_exception_data_template
kono
parents:
diff changeset
2428 = objc_start_struct (get_identifier (UTAG_EXCDATA));
kono
parents:
diff changeset
2429
kono
parents:
diff changeset
2430 /* int buf[OBJC_JBLEN]; */
kono
parents:
diff changeset
2431
kono
parents:
diff changeset
2432 temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
kono
parents:
diff changeset
2433 decls = add_field_decl (temp_type, "buf", &chain);
kono
parents:
diff changeset
2434
kono
parents:
diff changeset
2435 /* void *pointers[4]; */
kono
parents:
diff changeset
2436
kono
parents:
diff changeset
2437 temp_type = build_sized_array_type (ptr_type_node, 4);
kono
parents:
diff changeset
2438 add_field_decl (temp_type, "pointers", &chain);
kono
parents:
diff changeset
2439
kono
parents:
diff changeset
2440 objc_finish_struct (objc_exception_data_template, decls);
kono
parents:
diff changeset
2441
kono
parents:
diff changeset
2442 /* int _setjmp(...); */
kono
parents:
diff changeset
2443 /* If the user includes <setjmp.h>, this shall be superseded by
kono
parents:
diff changeset
2444 'int _setjmp(jmp_buf);' */
kono
parents:
diff changeset
2445 temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
kono
parents:
diff changeset
2446 objc_setjmp_decl
kono
parents:
diff changeset
2447 = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
kono
parents:
diff changeset
2448
kono
parents:
diff changeset
2449 /* id objc_exception_extract(struct _objc_exception_data *); */
kono
parents:
diff changeset
2450 temp_type
kono
parents:
diff changeset
2451 = build_function_type_list (objc_object_type,
kono
parents:
diff changeset
2452 build_pointer_type (objc_exception_data_template),
kono
parents:
diff changeset
2453 NULL_TREE);
kono
parents:
diff changeset
2454 objc_exception_extract_decl
kono
parents:
diff changeset
2455 = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2456 NULL_TREE);
kono
parents:
diff changeset
2457 /* void objc_exception_try_enter(struct _objc_exception_data *); */
kono
parents:
diff changeset
2458 /* void objc_exception_try_exit(struct _objc_exception_data *); */
kono
parents:
diff changeset
2459 temp_type
kono
parents:
diff changeset
2460 = build_function_type_list (void_type_node,
kono
parents:
diff changeset
2461 build_pointer_type (objc_exception_data_template),
kono
parents:
diff changeset
2462 NULL_TREE);
kono
parents:
diff changeset
2463 objc_exception_try_enter_decl
kono
parents:
diff changeset
2464 = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2465 NULL_TREE);
kono
parents:
diff changeset
2466 objc_exception_try_exit_decl
kono
parents:
diff changeset
2467 = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2468 NULL_TREE);
kono
parents:
diff changeset
2469
kono
parents:
diff changeset
2470 /* int objc_exception_match(id, id); */
kono
parents:
diff changeset
2471 temp_type
kono
parents:
diff changeset
2472 = build_function_type_list (integer_type_node,
kono
parents:
diff changeset
2473 objc_object_type, objc_object_type, NULL_TREE);
kono
parents:
diff changeset
2474 objc_exception_match_decl
kono
parents:
diff changeset
2475 = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2476 NULL_TREE);
kono
parents:
diff changeset
2477
kono
parents:
diff changeset
2478 /* id objc_assign_ivar (id, id, unsigned int); */
kono
parents:
diff changeset
2479 /* id objc_assign_ivar_Fast (id, id, unsigned int)
kono
parents:
diff changeset
2480 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
kono
parents:
diff changeset
2481 temp_type
kono
parents:
diff changeset
2482 = build_function_type_list (objc_object_type,
kono
parents:
diff changeset
2483 objc_object_type,
kono
parents:
diff changeset
2484 objc_object_type,
kono
parents:
diff changeset
2485 unsigned_type_node,
kono
parents:
diff changeset
2486 NULL_TREE);
kono
parents:
diff changeset
2487 objc_assign_ivar_decl
kono
parents:
diff changeset
2488 = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
kono
parents:
diff changeset
2489 NULL, NULL_TREE);
kono
parents:
diff changeset
2490 #ifdef OFFS_ASSIGNIVAR_FAST
kono
parents:
diff changeset
2491 objc_assign_ivar_fast_decl
kono
parents:
diff changeset
2492 = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
kono
parents:
diff changeset
2493 NOT_BUILT_IN, NULL, NULL_TREE);
kono
parents:
diff changeset
2494 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
kono
parents:
diff changeset
2495 = tree_cons (get_identifier ("hard_coded_address"),
kono
parents:
diff changeset
2496 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
kono
parents:
diff changeset
2497 NULL_TREE);
kono
parents:
diff changeset
2498 #else
kono
parents:
diff changeset
2499 /* Default to slower ivar method. */
kono
parents:
diff changeset
2500 objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
kono
parents:
diff changeset
2501 #endif
kono
parents:
diff changeset
2502
kono
parents:
diff changeset
2503 /* id objc_assign_global (id, id *); */
kono
parents:
diff changeset
2504 /* id objc_assign_strongCast (id, id *); */
kono
parents:
diff changeset
2505 temp_type = build_function_type_list (objc_object_type,
kono
parents:
diff changeset
2506 objc_object_type,
kono
parents:
diff changeset
2507 build_pointer_type (objc_object_type),
kono
parents:
diff changeset
2508 NULL_TREE);
kono
parents:
diff changeset
2509 objc_assign_global_decl
kono
parents:
diff changeset
2510 = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2511 NULL_TREE);
kono
parents:
diff changeset
2512 objc_assign_strong_cast_decl
kono
parents:
diff changeset
2513 = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
kono
parents:
diff changeset
2514 NULL_TREE);
kono
parents:
diff changeset
2515 }
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 /* --- NeXT V1 SJLJ Exceptions --- */
kono
parents:
diff changeset
2518
kono
parents:
diff changeset
2519 /* Build "objc_exception_try_exit(&_stack)". */
kono
parents:
diff changeset
2520
kono
parents:
diff changeset
2521 static tree
kono
parents:
diff changeset
2522 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
kono
parents:
diff changeset
2523 {
kono
parents:
diff changeset
2524 tree t;
kono
parents:
diff changeset
2525 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
kono
parents:
diff changeset
2526 t = tree_cons (NULL, t, NULL);
kono
parents:
diff changeset
2527 t = build_function_call (input_location,
kono
parents:
diff changeset
2528 objc_exception_try_exit_decl, t);
kono
parents:
diff changeset
2529 return t;
kono
parents:
diff changeset
2530 }
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 /* Build
kono
parents:
diff changeset
2533 objc_exception_try_enter (&_stack);
kono
parents:
diff changeset
2534 if (_setjmp(&_stack.buf))
kono
parents:
diff changeset
2535 ;
kono
parents:
diff changeset
2536 else
kono
parents:
diff changeset
2537 ;
kono
parents:
diff changeset
2538 Return the COND_EXPR. Note that the THEN and ELSE fields are left
kono
parents:
diff changeset
2539 empty, ready for the caller to fill them in. */
kono
parents:
diff changeset
2540
kono
parents:
diff changeset
2541 static tree
kono
parents:
diff changeset
2542 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
kono
parents:
diff changeset
2543 {
kono
parents:
diff changeset
2544 tree t, enter, sj, cond;
kono
parents:
diff changeset
2545
kono
parents:
diff changeset
2546 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
kono
parents:
diff changeset
2547 t = tree_cons (NULL, t, NULL);
kono
parents:
diff changeset
2548 enter = build_function_call (input_location,
kono
parents:
diff changeset
2549 objc_exception_try_enter_decl, t);
kono
parents:
diff changeset
2550
kono
parents:
diff changeset
2551 t = objc_build_component_ref ((*ctcp)->stack_decl,
kono
parents:
diff changeset
2552 get_identifier ("buf"));
kono
parents:
diff changeset
2553 t = build_fold_addr_expr_loc (input_location, t);
kono
parents:
diff changeset
2554 #ifdef OBJCPLUS
kono
parents:
diff changeset
2555 /* Convert _setjmp argument to type that is expected. */
kono
parents:
diff changeset
2556 if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
kono
parents:
diff changeset
2557 t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
kono
parents:
diff changeset
2558 else
kono
parents:
diff changeset
2559 t = convert (ptr_type_node, t);
kono
parents:
diff changeset
2560 #else
kono
parents:
diff changeset
2561 t = convert (ptr_type_node, t);
kono
parents:
diff changeset
2562 #endif
kono
parents:
diff changeset
2563 t = tree_cons (NULL, t, NULL);
kono
parents:
diff changeset
2564 sj = build_function_call (input_location,
kono
parents:
diff changeset
2565 objc_setjmp_decl, t);
kono
parents:
diff changeset
2566
kono
parents:
diff changeset
2567 cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
kono
parents:
diff changeset
2568 cond = c_common_truthvalue_conversion (input_location, cond);
kono
parents:
diff changeset
2569
kono
parents:
diff changeset
2570 return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
kono
parents:
diff changeset
2571 }
kono
parents:
diff changeset
2572
kono
parents:
diff changeset
2573 /* Build:
kono
parents:
diff changeset
2574
kono
parents:
diff changeset
2575 DECL = objc_exception_extract(&_stack); */
kono
parents:
diff changeset
2576
kono
parents:
diff changeset
2577 static tree
kono
parents:
diff changeset
2578 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
kono
parents:
diff changeset
2579 {
kono
parents:
diff changeset
2580 tree t;
kono
parents:
diff changeset
2581
kono
parents:
diff changeset
2582 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
kono
parents:
diff changeset
2583 t = tree_cons (NULL, t, NULL);
kono
parents:
diff changeset
2584 t = build_function_call (input_location,
kono
parents:
diff changeset
2585 objc_exception_extract_decl, t);
kono
parents:
diff changeset
2586 t = convert (TREE_TYPE (decl), t);
kono
parents:
diff changeset
2587 t = build2 (MODIFY_EXPR, void_type_node, decl, t);
kono
parents:
diff changeset
2588
kono
parents:
diff changeset
2589 return t;
kono
parents:
diff changeset
2590 }
kono
parents:
diff changeset
2591
kono
parents:
diff changeset
2592 /* Build
kono
parents:
diff changeset
2593 if (objc_exception_match(obj_get_class(TYPE), _caught)
kono
parents:
diff changeset
2594 BODY
kono
parents:
diff changeset
2595 else if (...)
kono
parents:
diff changeset
2596 ...
kono
parents:
diff changeset
2597 else
kono
parents:
diff changeset
2598 {
kono
parents:
diff changeset
2599 _rethrow = _caught;
kono
parents:
diff changeset
2600 objc_exception_try_exit(&_stack);
kono
parents:
diff changeset
2601 }
kono
parents:
diff changeset
2602 from the sequence of CATCH_EXPRs in the current try context. */
kono
parents:
diff changeset
2603
kono
parents:
diff changeset
2604 static tree
kono
parents:
diff changeset
2605 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
kono
parents:
diff changeset
2606 {
kono
parents:
diff changeset
2607 tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
kono
parents:
diff changeset
2608 tree catch_seq, t;
kono
parents:
diff changeset
2609 tree *last = &catch_seq;
kono
parents:
diff changeset
2610 bool saw_id = false;
kono
parents:
diff changeset
2611
kono
parents:
diff changeset
2612 for (; !tsi_end_p (i); tsi_next (&i))
kono
parents:
diff changeset
2613 {
kono
parents:
diff changeset
2614 tree stmt = tsi_stmt (i);
kono
parents:
diff changeset
2615 tree type = CATCH_TYPES (stmt);
kono
parents:
diff changeset
2616 tree body = CATCH_BODY (stmt);
kono
parents:
diff changeset
2617
kono
parents:
diff changeset
2618 if (type != error_mark_node
kono
parents:
diff changeset
2619 && objc_is_object_id (TREE_TYPE (type)))
kono
parents:
diff changeset
2620 {
kono
parents:
diff changeset
2621 *last = body;
kono
parents:
diff changeset
2622 saw_id = true;
kono
parents:
diff changeset
2623 break;
kono
parents:
diff changeset
2624 }
kono
parents:
diff changeset
2625 else
kono
parents:
diff changeset
2626 {
kono
parents:
diff changeset
2627 tree args, cond;
kono
parents:
diff changeset
2628
kono
parents:
diff changeset
2629 if (type == error_mark_node)
kono
parents:
diff changeset
2630 cond = error_mark_node;
kono
parents:
diff changeset
2631 else
kono
parents:
diff changeset
2632 {
kono
parents:
diff changeset
2633 args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
kono
parents:
diff changeset
2634 t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
kono
parents:
diff changeset
2635 args = tree_cons (NULL, t, args);
kono
parents:
diff changeset
2636 t = build_function_call (input_location,
kono
parents:
diff changeset
2637 objc_exception_match_decl, args);
kono
parents:
diff changeset
2638 cond = c_common_truthvalue_conversion (input_location, t);
kono
parents:
diff changeset
2639 }
kono
parents:
diff changeset
2640 t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
kono
parents:
diff changeset
2641 SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
kono
parents:
diff changeset
2642
kono
parents:
diff changeset
2643 *last = t;
kono
parents:
diff changeset
2644 last = &COND_EXPR_ELSE (t);
kono
parents:
diff changeset
2645 }
kono
parents:
diff changeset
2646 }
kono
parents:
diff changeset
2647
kono
parents:
diff changeset
2648 if (!saw_id)
kono
parents:
diff changeset
2649 {
kono
parents:
diff changeset
2650 t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
kono
parents:
diff changeset
2651 (*ctcp)->caught_decl);
kono
parents:
diff changeset
2652 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
kono
parents:
diff changeset
2653 append_to_statement_list (t, last);
kono
parents:
diff changeset
2654
kono
parents:
diff changeset
2655 t = next_sjlj_build_try_exit (ctcp);
kono
parents:
diff changeset
2656 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
kono
parents:
diff changeset
2657 append_to_statement_list (t, last);
kono
parents:
diff changeset
2658 }
kono
parents:
diff changeset
2659
kono
parents:
diff changeset
2660 return catch_seq;
kono
parents:
diff changeset
2661 }
kono
parents:
diff changeset
2662
kono
parents:
diff changeset
2663 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
kono
parents:
diff changeset
2664 exception handling. We aim to build:
kono
parents:
diff changeset
2665
kono
parents:
diff changeset
2666 {
kono
parents:
diff changeset
2667 struct _objc_exception_data _stack;
kono
parents:
diff changeset
2668 id _rethrow = 0;
kono
parents:
diff changeset
2669 try
kono
parents:
diff changeset
2670 {
kono
parents:
diff changeset
2671 objc_exception_try_enter (&_stack);
kono
parents:
diff changeset
2672 if (_setjmp(&_stack.buf))
kono
parents:
diff changeset
2673 {
kono
parents:
diff changeset
2674 id _caught = objc_exception_extract(&_stack);
kono
parents:
diff changeset
2675 objc_exception_try_enter (&_stack);
kono
parents:
diff changeset
2676 if (_setjmp(&_stack.buf))
kono
parents:
diff changeset
2677 _rethrow = objc_exception_extract(&_stack);
kono
parents:
diff changeset
2678 else
kono
parents:
diff changeset
2679 CATCH-LIST
kono
parents:
diff changeset
2680 }
kono
parents:
diff changeset
2681 else
kono
parents:
diff changeset
2682 TRY-BLOCK
kono
parents:
diff changeset
2683 }
kono
parents:
diff changeset
2684 finally
kono
parents:
diff changeset
2685 {
kono
parents:
diff changeset
2686 if (!_rethrow)
kono
parents:
diff changeset
2687 objc_exception_try_exit(&_stack);
kono
parents:
diff changeset
2688 FINALLY-BLOCK
kono
parents:
diff changeset
2689 if (_rethrow)
kono
parents:
diff changeset
2690 objc_exception_throw(_rethrow);
kono
parents:
diff changeset
2691 }
kono
parents:
diff changeset
2692 }
kono
parents:
diff changeset
2693
kono
parents:
diff changeset
2694 If CATCH-LIST is empty, we can omit all of the block containing
kono
parents:
diff changeset
2695 "_caught" except for the setting of _rethrow. Note the use of
kono
parents:
diff changeset
2696 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
kono
parents:
diff changeset
2697 but handles goto and other exits from the block. */
kono
parents:
diff changeset
2698
kono
parents:
diff changeset
2699 static tree
kono
parents:
diff changeset
2700 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
kono
parents:
diff changeset
2701 {
kono
parents:
diff changeset
2702 tree rethrow_decl, stack_decl, t;
kono
parents:
diff changeset
2703 tree catch_seq, try_fin, bind;
kono
parents:
diff changeset
2704 struct objc_try_context *cur_try_context = *ctcp;
kono
parents:
diff changeset
2705
kono
parents:
diff changeset
2706 /* Create the declarations involved. */
kono
parents:
diff changeset
2707 t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
kono
parents:
diff changeset
2708 stack_decl = objc_create_temporary_var (t, NULL);
kono
parents:
diff changeset
2709 cur_try_context->stack_decl = stack_decl;
kono
parents:
diff changeset
2710
kono
parents:
diff changeset
2711 rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
kono
parents:
diff changeset
2712 cur_try_context->rethrow_decl = rethrow_decl;
kono
parents:
diff changeset
2713 TREE_CHAIN (rethrow_decl) = stack_decl;
kono
parents:
diff changeset
2714
kono
parents:
diff changeset
2715 /* Build the outermost variable binding level. */
kono
parents:
diff changeset
2716 bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
kono
parents:
diff changeset
2717 SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
kono
parents:
diff changeset
2718 TREE_SIDE_EFFECTS (bind) = 1;
kono
parents:
diff changeset
2719
kono
parents:
diff changeset
2720 /* Initialize rethrow_decl. */
kono
parents:
diff changeset
2721 t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
kono
parents:
diff changeset
2722 convert (objc_object_type, null_pointer_node));
kono
parents:
diff changeset
2723 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
kono
parents:
diff changeset
2724 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
kono
parents:
diff changeset
2725
kono
parents:
diff changeset
2726 /* Build the outermost TRY_FINALLY_EXPR. */
kono
parents:
diff changeset
2727 try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
kono
parents:
diff changeset
2728 SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
kono
parents:
diff changeset
2729 TREE_SIDE_EFFECTS (try_fin) = 1;
kono
parents:
diff changeset
2730 append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
kono
parents:
diff changeset
2731
kono
parents:
diff changeset
2732 /* Create the complete catch sequence. */
kono
parents:
diff changeset
2733 if (cur_try_context->catch_list)
kono
parents:
diff changeset
2734 {
kono
parents:
diff changeset
2735 tree caught_decl = objc_build_exc_ptr (ctcp);
kono
parents:
diff changeset
2736 catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
kono
parents:
diff changeset
2737 TREE_SIDE_EFFECTS (catch_seq) = 1;
kono
parents:
diff changeset
2738
kono
parents:
diff changeset
2739 t = next_sjlj_build_exc_extract (ctcp, caught_decl);
kono
parents:
diff changeset
2740 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
kono
parents:
diff changeset
2741
kono
parents:
diff changeset
2742 t = next_sjlj_build_enter_and_setjmp (ctcp);
kono
parents:
diff changeset
2743 COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
kono
parents:
diff changeset
2744 COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
kono
parents:
diff changeset
2745 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
kono
parents:
diff changeset
2746 }
kono
parents:
diff changeset
2747 else
kono
parents:
diff changeset
2748 catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
kono
parents:
diff changeset
2749 SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
kono
parents:
diff changeset
2750
kono
parents:
diff changeset
2751 /* Build the main register-and-try if statement. */
kono
parents:
diff changeset
2752 t = next_sjlj_build_enter_and_setjmp (ctcp);
kono
parents:
diff changeset
2753 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
kono
parents:
diff changeset
2754 COND_EXPR_THEN (t) = catch_seq;
kono
parents:
diff changeset
2755 COND_EXPR_ELSE (t) = cur_try_context->try_body;
kono
parents:
diff changeset
2756 TREE_OPERAND (try_fin, 0) = t;
kono
parents:
diff changeset
2757
kono
parents:
diff changeset
2758 /* Build the complete FINALLY statement list. */
kono
parents:
diff changeset
2759 t = next_sjlj_build_try_exit (ctcp);
kono
parents:
diff changeset
2760 t = build_stmt (input_location, COND_EXPR,
kono
parents:
diff changeset
2761 c_common_truthvalue_conversion
kono
parents:
diff changeset
2762 (input_location, rethrow_decl),
kono
parents:
diff changeset
2763 NULL, t);
kono
parents:
diff changeset
2764 SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
kono
parents:
diff changeset
2765 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
kono
parents:
diff changeset
2766
kono
parents:
diff changeset
2767 append_to_statement_list (cur_try_context->finally_body,
kono
parents:
diff changeset
2768 &TREE_OPERAND (try_fin, 1));
kono
parents:
diff changeset
2769
kono
parents:
diff changeset
2770 t = tree_cons (NULL, rethrow_decl, NULL);
kono
parents:
diff changeset
2771 t = build_function_call (input_location,
kono
parents:
diff changeset
2772 objc_exception_throw_decl, t);
kono
parents:
diff changeset
2773 t = build_stmt (input_location, COND_EXPR,
kono
parents:
diff changeset
2774 c_common_truthvalue_conversion (input_location,
kono
parents:
diff changeset
2775 rethrow_decl),
kono
parents:
diff changeset
2776 t, NULL);
kono
parents:
diff changeset
2777 SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
kono
parents:
diff changeset
2778 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
kono
parents:
diff changeset
2779
kono
parents:
diff changeset
2780 return bind;
kono
parents:
diff changeset
2781 }
kono
parents:
diff changeset
2782
kono
parents:
diff changeset
2783 /* We do not expect this to be used at the moment.
kono
parents:
diff changeset
2784 If (a) it is possible to implement unwinder exceptions.
kono
parents:
diff changeset
2785 (b) we do it... then it might be possibly useful.
kono
parents:
diff changeset
2786 */
kono
parents:
diff changeset
2787 static GTY(()) tree objc_eh_personality_decl;
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 static tree
kono
parents:
diff changeset
2790 objc_eh_runtime_type (tree type)
kono
parents:
diff changeset
2791 {
kono
parents:
diff changeset
2792 tree ident, eh_id, decl, str;
kono
parents:
diff changeset
2793
kono
parents:
diff changeset
2794 gcc_unreachable ();
kono
parents:
diff changeset
2795 if (type == error_mark_node)
kono
parents:
diff changeset
2796 {
kono
parents:
diff changeset
2797 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
kono
parents:
diff changeset
2798 to prevent an ICE. Note that we know that the compiler will
kono
parents:
diff changeset
2799 terminate with an error and this 'ErrorMarkNode' class name will
kono
parents:
diff changeset
2800 never be actually used. */
kono
parents:
diff changeset
2801 ident = get_identifier ("ErrorMarkNode");
kono
parents:
diff changeset
2802 goto make_err_class;
kono
parents:
diff changeset
2803 }
kono
parents:
diff changeset
2804
kono
parents:
diff changeset
2805 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
kono
parents:
diff changeset
2806 {
kono
parents:
diff changeset
2807 ident = get_identifier ("id");
kono
parents:
diff changeset
2808 goto make_err_class;
kono
parents:
diff changeset
2809 }
kono
parents:
diff changeset
2810
kono
parents:
diff changeset
2811 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
kono
parents:
diff changeset
2812 {
kono
parents:
diff changeset
2813 #ifdef OBJCPLUS
kono
parents:
diff changeset
2814 /* This routine is also called for c++'s catch clause; in which case,
kono
parents:
diff changeset
2815 we use c++'s typeinfo decl. */
kono
parents:
diff changeset
2816 return build_eh_type_type (type);
kono
parents:
diff changeset
2817 #else
kono
parents:
diff changeset
2818 error ("non-objective-c type %qT cannot be caught", type);
kono
parents:
diff changeset
2819 ident = get_identifier ("ErrorMarkNode");
kono
parents:
diff changeset
2820 goto make_err_class;
kono
parents:
diff changeset
2821 #endif
kono
parents:
diff changeset
2822 }
kono
parents:
diff changeset
2823 else
kono
parents:
diff changeset
2824 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
kono
parents:
diff changeset
2825
kono
parents:
diff changeset
2826 make_err_class:
kono
parents:
diff changeset
2827 /* If this class was already referenced, then it will be output during
kono
parents:
diff changeset
2828 meta-data emission, so we don't need to do it here. */
kono
parents:
diff changeset
2829 decl = get_objc_string_decl (ident, class_names);
kono
parents:
diff changeset
2830 eh_id = add_objc_string (ident, class_names);
kono
parents:
diff changeset
2831 if (!decl)
kono
parents:
diff changeset
2832 {
kono
parents:
diff changeset
2833 /* Not found ... so we need to build it - from the freshly-entered id. */
kono
parents:
diff changeset
2834 decl = get_objc_string_decl (ident, class_names);
kono
parents:
diff changeset
2835 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
kono
parents:
diff changeset
2836 IDENTIFIER_POINTER (ident));
kono
parents:
diff changeset
2837 /* We have to finalize this var here, because this might be called after
kono
parents:
diff changeset
2838 all the other metadata strings have been emitted. */
kono
parents:
diff changeset
2839 finish_var_decl (decl, str);
kono
parents:
diff changeset
2840 }
kono
parents:
diff changeset
2841 return eh_id;
kono
parents:
diff changeset
2842 }
kono
parents:
diff changeset
2843
kono
parents:
diff changeset
2844 /* For NeXT ABI 0 and 1, the personality routines are just those of the
kono
parents:
diff changeset
2845 underlying language. */
kono
parents:
diff changeset
2846
kono
parents:
diff changeset
2847 static tree
kono
parents:
diff changeset
2848 objc_eh_personality (void)
kono
parents:
diff changeset
2849 {
kono
parents:
diff changeset
2850 if (!objc_eh_personality_decl)
kono
parents:
diff changeset
2851 #ifndef OBJCPLUS
kono
parents:
diff changeset
2852 objc_eh_personality_decl = build_personality_function ("gcc");
kono
parents:
diff changeset
2853 #else
kono
parents:
diff changeset
2854 objc_eh_personality_decl = build_personality_function ("gxx");
kono
parents:
diff changeset
2855 #endif
kono
parents:
diff changeset
2856 return objc_eh_personality_decl;
kono
parents:
diff changeset
2857 }
kono
parents:
diff changeset
2858
kono
parents:
diff changeset
2859 /* --- interfaces --- */
kono
parents:
diff changeset
2860
kono
parents:
diff changeset
2861 static tree
kono
parents:
diff changeset
2862 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2863 {
kono
parents:
diff changeset
2864 tree t;
kono
parents:
diff changeset
2865 vec<tree, va_gc> *parms;
kono
parents:
diff changeset
2866 vec_alloc (parms, 1);
kono
parents:
diff changeset
2867 /* A throw is just a call to the runtime throw function with the
kono
parents:
diff changeset
2868 object as a parameter. */
kono
parents:
diff changeset
2869 parms->quick_push (throw_expr);
kono
parents:
diff changeset
2870 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
kono
parents:
diff changeset
2871 NULL);
kono
parents:
diff changeset
2872 vec_free (parms);
kono
parents:
diff changeset
2873 return add_stmt (t);
kono
parents:
diff changeset
2874 }
kono
parents:
diff changeset
2875
kono
parents:
diff changeset
2876 /* Build __builtin_eh_pointer, or the moral equivalent. In the case
kono
parents:
diff changeset
2877 of Darwin, we'll arrange for it to be initialized (and associated
kono
parents:
diff changeset
2878 with a binding) later. */
kono
parents:
diff changeset
2879
kono
parents:
diff changeset
2880 static tree
kono
parents:
diff changeset
2881 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
kono
parents:
diff changeset
2882 {
kono
parents:
diff changeset
2883 if (flag_objc_sjlj_exceptions)
kono
parents:
diff changeset
2884 {
kono
parents:
diff changeset
2885 tree var = (*cur_try_context)->caught_decl;
kono
parents:
diff changeset
2886 if (!var)
kono
parents:
diff changeset
2887 {
kono
parents:
diff changeset
2888 var = objc_create_temporary_var (objc_object_type, NULL);
kono
parents:
diff changeset
2889 (*cur_try_context)->caught_decl = var;
kono
parents:
diff changeset
2890 }
kono
parents:
diff changeset
2891 return var;
kono
parents:
diff changeset
2892 }
kono
parents:
diff changeset
2893 else
kono
parents:
diff changeset
2894 {
kono
parents:
diff changeset
2895 tree t;
kono
parents:
diff changeset
2896 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
kono
parents:
diff changeset
2897 t = build_call_expr (t, 1, integer_zero_node);
kono
parents:
diff changeset
2898 return fold_convert (objc_object_type, t);
kono
parents:
diff changeset
2899 }
kono
parents:
diff changeset
2900 }
kono
parents:
diff changeset
2901
kono
parents:
diff changeset
2902 static tree
kono
parents:
diff changeset
2903 begin_catch (struct objc_try_context **cur_try_context, tree type,
kono
parents:
diff changeset
2904 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2905 {
kono
parents:
diff changeset
2906 tree t;
kono
parents:
diff changeset
2907 /* Record the data for the catch in the try context so that we can
kono
parents:
diff changeset
2908 finalize it later. We treat ellipsis the same way as catching
kono
parents:
diff changeset
2909 with 'id xyz'. */
kono
parents:
diff changeset
2910 t = build_stmt (input_location, CATCH_EXPR, type, compound);
kono
parents:
diff changeset
2911 (*cur_try_context)->current_catch = t;
kono
parents:
diff changeset
2912
kono
parents:
diff changeset
2913 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
kono
parents:
diff changeset
2914 t = objc_build_exc_ptr (cur_try_context);
kono
parents:
diff changeset
2915 t = convert (TREE_TYPE (decl), t);
kono
parents:
diff changeset
2916 return build2 (MODIFY_EXPR, void_type_node, decl, t);
kono
parents:
diff changeset
2917 }
kono
parents:
diff changeset
2918
kono
parents:
diff changeset
2919 static void
kono
parents:
diff changeset
2920 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
kono
parents:
diff changeset
2921 {
kono
parents:
diff changeset
2922 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
kono
parents:
diff changeset
2923 }
kono
parents:
diff changeset
2924
kono
parents:
diff changeset
2925 static tree
kono
parents:
diff changeset
2926 finish_try_stmt (struct objc_try_context **cur_try_context)
kono
parents:
diff changeset
2927 {
kono
parents:
diff changeset
2928 tree stmt;
kono
parents:
diff changeset
2929 struct objc_try_context *c = *cur_try_context;
kono
parents:
diff changeset
2930 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
kono
parents:
diff changeset
2931 if (flag_objc_sjlj_exceptions)
kono
parents:
diff changeset
2932 {
kono
parents:
diff changeset
2933 bool save = in_late_binary_op;
kono
parents:
diff changeset
2934 in_late_binary_op = true;
kono
parents:
diff changeset
2935 if (!c->finally_body)
kono
parents:
diff changeset
2936 {
kono
parents:
diff changeset
2937 c->finally_locus = input_location;
kono
parents:
diff changeset
2938 c->end_finally_locus = input_location;
kono
parents:
diff changeset
2939 }
kono
parents:
diff changeset
2940 stmt = next_sjlj_build_try_catch_finally (cur_try_context);
kono
parents:
diff changeset
2941 in_late_binary_op = save;
kono
parents:
diff changeset
2942 }
kono
parents:
diff changeset
2943 else
kono
parents:
diff changeset
2944 /* This doesn't happen at the moment... but maybe one day... */
kono
parents:
diff changeset
2945 {
kono
parents:
diff changeset
2946 /* Otherwise, nest the CATCH inside a FINALLY. */
kono
parents:
diff changeset
2947 stmt = c->try_body;
kono
parents:
diff changeset
2948 if (c->catch_list)
kono
parents:
diff changeset
2949 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
kono
parents:
diff changeset
2950 if (c->finally_body)
kono
parents:
diff changeset
2951 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
kono
parents:
diff changeset
2952 }
kono
parents:
diff changeset
2953 return stmt;
kono
parents:
diff changeset
2954 }
kono
parents:
diff changeset
2955
kono
parents:
diff changeset
2956 #include "gt-objc-objc-next-runtime-abi-01.h"