Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / class-accessors.c
1 /**
2  * \file
3  * Copyright 2016 Microsoft
4  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
5  */
6 #include <mono/metadata/class-internals.h>
7 #include <mono/metadata/tabledefs.h>
8
9
10 typedef enum {
11         PROP_MARSHAL_INFO = 1, /* MonoMarshalType */
12         PROP_REF_INFO_HANDLE = 2, /* gchandle */
13         PROP_EXCEPTION_DATA = 3, /* MonoErrorBoxed* */
14         PROP_NESTED_CLASSES = 4, /* GList* */
15         PROP_PROPERTY_INFO = 5, /* MonoClassPropertyInfo* */
16         PROP_EVENT_INFO = 6, /* MonoClassEventInfo* */
17         PROP_FIELD_DEF_VALUES = 7, /* MonoFieldDefaultValue* */
18         PROP_DECLSEC_FLAGS = 8 /* guint32 */
19 }  InfrequentDataKind;
20
21 /* Accessors based on class kind*/
22
23 /*
24 * mono_class_get_generic_class:
25 *
26 *   Return the MonoGenericClass of @klass, which MUST be a generic instance.
27 */
28 MonoGenericClass*
29 mono_class_get_generic_class (MonoClass *klass)
30 {
31         g_assert (mono_class_is_ginst (klass));
32         return ((MonoClassGenericInst*)klass)->generic_class;
33 }
34
35 /*
36 * mono_class_try_get_generic_class:
37 *
38 *   Return the MonoGenericClass if @klass is a ginst, NULL otherwise
39 */
40 MonoGenericClass*
41 mono_class_try_get_generic_class (MonoClass *klass)
42 {
43         if (mono_class_is_ginst (klass))
44                 return ((MonoClassGenericInst*)klass)->generic_class;
45         return NULL;
46 }
47
48 /**
49  * mono_class_get_flags:
50  * \param klass the MonoClass to act on
51  * \returns the \c TypeAttributes flags of \p klass.
52  * See the \c TYPE_ATTRIBUTE_* definitions in \c tabledefs.h for the different values.
53  */
54 guint32
55 mono_class_get_flags (MonoClass *klass)
56 {
57         switch (klass->class_kind) {
58         case MONO_CLASS_DEF:
59         case MONO_CLASS_GTD:
60                 return ((MonoClassDef*)klass)->flags;
61         case MONO_CLASS_GINST:
62                 return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
63         case MONO_CLASS_GPARAM:
64                 return TYPE_ATTRIBUTE_PUBLIC;
65         case MONO_CLASS_ARRAY:
66                 /* all arrays are marked serializable and sealed, bug #42779 */
67                 return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
68         case MONO_CLASS_POINTER:
69                 return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
70         }
71         g_assert_not_reached ();
72 }
73
74 void
75 mono_class_set_flags (MonoClass *klass, guint32 flags)
76 {
77         g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
78         ((MonoClassDef*)klass)->flags = flags;
79 }
80
81 /*
82  * mono_class_get_generic_container:
83  *
84  *   Return the generic container of KLASS which should be a generic type definition.
85  */
86 MonoGenericContainer*
87 mono_class_get_generic_container (MonoClass *klass)
88 {
89         g_assert (mono_class_is_gtd (klass));
90
91         return ((MonoClassGtd*)klass)->generic_container;
92 }
93
94 MonoGenericContainer*
95 mono_class_try_get_generic_container (MonoClass *klass)
96 {
97         if (mono_class_is_gtd (klass))
98                 return ((MonoClassGtd*)klass)->generic_container;
99         return NULL;
100 }
101
102
103 void
104 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
105 {
106         g_assert (mono_class_is_gtd (klass));
107
108         ((MonoClassGtd*)klass)->generic_container = container;
109 }
110
111 /*
112  * mono_class_get_first_method_idx:
113  *
114  *   Return the table index of the first method for metadata classes.
115  */
116 guint32
117 mono_class_get_first_method_idx (MonoClass *klass)
118 {
119         g_assert (mono_class_has_static_metadata (klass));
120
121         return ((MonoClassDef*)klass)->first_method_idx;
122 }
123
124 void
125 mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
126 {
127         g_assert (mono_class_has_static_metadata (klass));
128
129         ((MonoClassDef*)klass)->first_method_idx = idx;
130 }
131
132 guint32
133 mono_class_get_first_field_idx (MonoClass *klass)
134 {
135         if (mono_class_is_ginst (klass))
136                 return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
137
138         g_assert (mono_class_has_static_metadata (klass));
139
140         return ((MonoClassDef*)klass)->first_field_idx;
141 }
142
143 void
144 mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
145 {
146         g_assert (mono_class_has_static_metadata (klass));
147
148         ((MonoClassDef*)klass)->first_field_idx = idx;
149 }
150
151 guint32
152 mono_class_get_method_count (MonoClass *klass)
153 {
154         switch (klass->class_kind) {
155         case MONO_CLASS_DEF:
156         case MONO_CLASS_GTD:
157                 return ((MonoClassDef*)klass)->method_count;
158         case MONO_CLASS_GINST:
159                 return mono_class_get_method_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
160         case MONO_CLASS_GPARAM:
161                 return 0;
162         case MONO_CLASS_ARRAY:
163                 return ((MonoClassArray*)klass)->method_count;
164         case MONO_CLASS_POINTER:
165                 return 0;
166         default:
167                 g_assert_not_reached ();
168                 return 0;
169         }
170 }
171
172 void
173 mono_class_set_method_count (MonoClass *klass, guint32 count)
174 {
175         switch (klass->class_kind) {
176         case MONO_CLASS_DEF:
177         case MONO_CLASS_GTD:
178                 ((MonoClassDef*)klass)->method_count = count;
179                 break;
180         case MONO_CLASS_GINST:
181                 break;
182         case MONO_CLASS_GPARAM:
183         case MONO_CLASS_POINTER:
184                 g_assert (count == 0);
185                 break;
186         case MONO_CLASS_ARRAY:
187                 ((MonoClassArray*)klass)->method_count = count;
188                 break;
189         default:
190                 g_assert_not_reached ();
191                 break;
192         }
193 }
194
195 guint32
196 mono_class_get_field_count (MonoClass *klass)
197 {
198         switch (klass->class_kind) {
199         case MONO_CLASS_DEF:
200         case MONO_CLASS_GTD:
201                 return ((MonoClassDef*)klass)->field_count;
202         case MONO_CLASS_GINST:
203                 return mono_class_get_field_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
204         case MONO_CLASS_GPARAM:
205         case MONO_CLASS_ARRAY:
206         case MONO_CLASS_POINTER:
207                 return 0;
208         default:
209                 g_assert_not_reached ();
210                 return 0;
211         }
212 }
213
214 void
215 mono_class_set_field_count (MonoClass *klass, guint32 count)
216 {
217         switch (klass->class_kind) {
218         case MONO_CLASS_DEF:
219         case MONO_CLASS_GTD:
220                 ((MonoClassDef*)klass)->field_count = count;
221                 break;
222         case MONO_CLASS_GINST:
223                 break;
224         case MONO_CLASS_GPARAM:
225         case MONO_CLASS_ARRAY:
226         case MONO_CLASS_POINTER:
227                 g_assert (count == 0);
228                 break;
229         default:
230                 g_assert_not_reached ();
231                 break;
232         }
233 }
234
235 MonoMarshalType*
236 mono_class_get_marshal_info (MonoClass *class)
237 {
238         return mono_property_bag_get (&class->infrequent_data, PROP_MARSHAL_INFO);
239 }
240
241 void
242 mono_class_set_marshal_info (MonoClass *class, MonoMarshalType *marshal_info)
243 {
244         marshal_info->head.tag = PROP_MARSHAL_INFO;
245         mono_property_bag_add (&class->infrequent_data, marshal_info);
246 }
247
248 typedef struct {
249         MonoPropertyBagItem head;
250         guint32 value;
251 } Uint32Property;
252
253 guint32
254 mono_class_get_ref_info_handle (MonoClass *class)
255 {
256         Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
257         return prop ? prop->value : 0;
258 }
259
260 guint32
261 mono_class_set_ref_info_handle (MonoClass *class, guint32 value)
262 {
263         if (!value) {
264                 Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
265                 if (prop)
266                         prop->value = 0;
267                 return 0;
268         }
269
270         Uint32Property *prop = mono_class_alloc (class, sizeof (Uint32Property));
271         prop->head.tag = PROP_REF_INFO_HANDLE;
272         prop->value = value;
273         prop = mono_property_bag_add (&class->infrequent_data, prop);
274         return prop->value;
275 }
276
277 typedef struct {
278         MonoPropertyBagItem head;
279         gpointer value;
280 } PointerProperty;
281
282 static void
283 set_pointer_property (MonoClass *klass, InfrequentDataKind property, gpointer value)
284 {
285         PointerProperty *prop = mono_class_alloc (klass, sizeof (PointerProperty));
286         prop->head.tag = property;
287         prop->value = value;
288         mono_property_bag_add (&klass->infrequent_data, prop);
289 }
290
291 static gpointer
292 get_pointer_property (MonoClass *klass, InfrequentDataKind property)
293 {
294         PointerProperty *prop = (PointerProperty*)mono_property_bag_get (&klass->infrequent_data, property);
295         return prop ? prop->value : NULL;
296 }
297
298 MonoErrorBoxed*
299 mono_class_get_exception_data (MonoClass *klass)
300 {
301         return (MonoErrorBoxed*)get_pointer_property (klass, PROP_EXCEPTION_DATA);
302 }
303
304 void
305 mono_class_set_exception_data (MonoClass *klass, MonoErrorBoxed *value)
306 {
307         set_pointer_property (klass, PROP_EXCEPTION_DATA, value);
308 }
309
310 GList*
311 mono_class_get_nested_classes_property (MonoClass *klass)
312 {
313         return (GList*)get_pointer_property (klass, PROP_NESTED_CLASSES);
314 }
315
316 void
317 mono_class_set_nested_classes_property (MonoClass *klass, GList *value)
318 {
319         set_pointer_property (klass, PROP_NESTED_CLASSES, value);
320 }
321
322 MonoClassPropertyInfo*
323 mono_class_get_property_info (MonoClass *klass)
324 {
325         return mono_property_bag_get (&klass->infrequent_data, PROP_PROPERTY_INFO);
326 }
327
328 void
329 mono_class_set_property_info (MonoClass *klass, MonoClassPropertyInfo *info)
330 {
331         info->head.tag = PROP_PROPERTY_INFO;
332         mono_property_bag_add (&klass->infrequent_data, info);
333 }
334
335 MonoClassEventInfo*
336 mono_class_get_event_info (MonoClass *klass)
337 {
338         return mono_property_bag_get (&klass->infrequent_data, PROP_EVENT_INFO);
339 }
340
341 void
342 mono_class_set_event_info (MonoClass *klass, MonoClassEventInfo *info)
343 {
344         info->head.tag = PROP_EVENT_INFO;
345         mono_property_bag_add (&klass->infrequent_data, info);
346 }
347
348 MonoFieldDefaultValue*
349 mono_class_get_field_def_values (MonoClass *klass)
350 {
351         return (MonoFieldDefaultValue*)get_pointer_property (klass, PROP_FIELD_DEF_VALUES);
352 }
353
354 void
355 mono_class_set_field_def_values (MonoClass *klass, MonoFieldDefaultValue *values)
356 {
357         set_pointer_property (klass, PROP_FIELD_DEF_VALUES, values);
358 }
359
360 guint32
361 mono_class_get_declsec_flags (MonoClass *class)
362 {
363         Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_DECLSEC_FLAGS);
364         return prop ? prop->value : 0;
365 }
366
367 void
368 mono_class_set_declsec_flags (MonoClass *class, guint32 value)
369 {
370         Uint32Property *prop = mono_class_alloc (class, sizeof (Uint32Property));
371         prop->head.tag = PROP_DECLSEC_FLAGS;
372         prop->value = value;
373         mono_property_bag_add (&class->infrequent_data, prop);
374 }
375
376 void
377 mono_class_set_is_com_object (MonoClass *klass)
378 {
379 #ifndef DISABLE_COM
380         mono_loader_lock ();
381         klass->is_com_object = 1;
382         mono_loader_unlock ();
383 #endif
384 }
385
386 MonoType*
387 mono_class_gtd_get_canonical_inst (MonoClass *klass)
388 {
389         g_assert (mono_class_is_gtd (klass));
390         return &((MonoClassGtd*)klass)->canonical_inst;
391 }