annotate gcc/objc/objc-next-runtime-abi-01.c @ 111:04ced10e8804

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