Merge pull request #1568 from akoeplinger/xbuild
[mono.git] / mono / mini / aot_dump.c
1 /*
2  * aot-dump.c: mono Ahead of Time compiler JSON dumping
3  *
4  * Author:
5  *   Joao Matos (joao.matos@xamarin.com)
6  *
7  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
8  */
9
10 #ifndef MONO_SMALL_CONFIG
11
12 #define JSON_INDENT_VALUE 2
13
14 typedef struct JsonWriter {
15         GString* text;
16         int indent;
17 } JsonWriter;
18
19 static void json_writer_init (JsonWriter* writer) MONO_INTERNAL;
20 static void json_writer_destroy (JsonWriter* writer);
21 static void json_writer_indent(JsonWriter* writer);
22 static void json_writer_indent_push(JsonWriter* writer);
23 static void json_writer_indent_pop(JsonWriter* writer);
24 static void json_writer_vprintf(JsonWriter* writer, const gchar *format, va_list args);
25 static void json_writer_printf(JsonWriter* writer, const gchar *format, ...);
26 static void json_writer_array_begin(JsonWriter* writer);
27 static void json_writer_array_end(JsonWriter* writer);
28 static void json_writer_object_begin(JsonWriter* writer);
29 static void json_writer_object_end(JsonWriter* writer);
30 static void json_writer_object_key(JsonWriter* writer, const gchar* format, ...);
31
32 static void json_writer_init (JsonWriter* writer)
33 {
34         g_assert (writer && "Expected a valid JSON writer instance");
35
36         writer->text = g_string_new ("");
37         writer->indent = 0;
38 }
39
40 static void json_writer_destroy (JsonWriter* writer)
41 {
42         g_assert (writer && "Expected a valid JSON writer instance");
43         g_string_free (writer->text, /*free_segment=*/TRUE);
44 }
45
46 static void json_writer_indent_push(JsonWriter* writer)
47 {
48         g_assert (writer && "Expected a valid JSON writer instance");
49         writer->indent += JSON_INDENT_VALUE;
50 }
51
52 static void json_writer_indent_pop(JsonWriter* writer)
53 {
54         g_assert (writer && "Expected a valid JSON writer instance");
55         writer->indent -= JSON_INDENT_VALUE;
56 }
57
58 static void json_writer_indent(JsonWriter* writer)
59 {
60         g_assert (writer && "Expected a valid JSON writer instance");
61
62         int i = 0;
63         for (i = 0; i < writer->indent; ++i)
64                 g_string_append_c (writer->text, ' ');
65 }
66
67 static void json_writer_vprintf(JsonWriter* writer, const gchar *format, va_list args)
68 {
69         g_assert (writer && "Expected a valid JSON writer instance");
70         g_string_append_vprintf (writer->text, format, args);
71 }
72
73 static void json_writer_printf(JsonWriter* writer, const gchar *format, ...)
74 {
75         g_assert (writer && "Expected a valid JSON writer instance");
76
77         va_list args;
78         va_start (args, format);
79
80         g_string_append_vprintf (writer->text, format, args);
81
82         va_end (args);
83 }
84
85 static void json_writer_array_begin(JsonWriter* writer)
86 {
87         g_assert (writer && "Expected a valid JSON writer instance");
88         g_string_append_printf (writer->text, "[\n");
89         writer->indent += JSON_INDENT_VALUE;
90 }
91
92 static void json_writer_array_end(JsonWriter* writer)
93 {
94         g_assert (writer && "Expected a valid JSON writer instance");
95         g_string_append_printf (writer->text, "]");
96         writer->indent -= JSON_INDENT_VALUE;
97 }
98
99 static void json_writer_object_begin(JsonWriter* writer)
100 {
101         g_assert (writer && "Expected a valid JSON writer instance");
102         json_writer_printf (writer, "{\n");
103         writer->indent += JSON_INDENT_VALUE;
104 }
105
106 static void json_writer_object_end(JsonWriter* writer)
107 {
108         g_assert (writer && "Expected a valid JSON writer instance");
109         json_writer_printf (writer, "}");
110 }
111
112 static void json_writer_object_key(JsonWriter* writer, const gchar* format, ...)
113 {
114         g_assert (writer && "Expected a valid JSON writer instance");
115
116         va_list args;
117         va_start (args, format);
118
119         g_string_append_printf (writer->text, "\"");
120         json_writer_vprintf (writer, format, args);
121         g_string_append_printf (writer->text, "\" : ");
122
123         va_end (args);
124 }
125
126 #define WRAPPER(e,n) n,
127 static const char* const
128 wrapper_type_names [MONO_WRAPPER_NUM + 1] = {
129 #include "mono/metadata/wrapper-types.h"
130         NULL
131 };
132
133 static G_GNUC_UNUSED const char*
134 get_wrapper_type_name (int type)
135 {
136         return wrapper_type_names [type];
137 }
138
139 //#define DUMP_PLT
140 //#define DUMP_GOT
141
142 static void aot_dump (MonoAotCompile *acfg)
143 {
144         FILE *dumpfile;
145         char * dumpname;
146
147         JsonWriter writer;
148         json_writer_init (&writer);
149
150         json_writer_object_begin(&writer);
151
152         // Methods
153         json_writer_indent (&writer);
154         json_writer_object_key(&writer, "methods");
155         json_writer_array_begin (&writer);
156
157         int i;
158         for (i = 0; i < acfg->nmethods; ++i) {
159                 MonoCompile *cfg;
160                 MonoMethod *method;
161                 MonoClass *klass;
162                 int index;
163
164                 cfg = acfg->cfgs [i];
165                 if (!cfg)
166                         continue;
167
168                 method = cfg->orig_method;
169
170                 json_writer_indent (&writer);
171                 json_writer_object_begin(&writer);
172
173                 json_writer_indent (&writer);
174                 json_writer_object_key(&writer, "name");
175                 json_writer_printf (&writer, "\"%s\",\n", method->name);
176
177                 json_writer_indent (&writer);
178                 json_writer_object_key(&writer, "signature");
179                 json_writer_printf (&writer, "\"%s\",\n", mono_method_full_name (method,
180                         /*signature=*/TRUE));
181
182                 json_writer_indent (&writer);
183                 json_writer_object_key(&writer, "code_size");
184                 json_writer_printf (&writer, "\"%d\",\n", cfg->code_size);
185
186                 klass = method->klass;
187
188                 json_writer_indent (&writer);
189                 json_writer_object_key(&writer, "class");
190                 json_writer_printf (&writer, "\"%s\",\n", klass->name);
191
192                 json_writer_indent (&writer);
193                 json_writer_object_key(&writer, "namespace");
194                 json_writer_printf (&writer, "\"%s\",\n", klass->name_space);
195
196                 json_writer_indent (&writer);
197                 json_writer_object_key(&writer, "wrapper_type");
198                 json_writer_printf (&writer, "\"%s\",\n", get_wrapper_type_name(method->wrapper_type));
199
200                 json_writer_indent_pop (&writer);
201                 json_writer_indent (&writer);
202                 json_writer_object_end (&writer);
203                 json_writer_printf (&writer, ",\n");
204         }
205
206         json_writer_indent_pop (&writer);
207         json_writer_indent (&writer);
208         json_writer_array_end (&writer);
209         json_writer_printf (&writer, ",\n");
210
211         // PLT entries
212 #ifdef DUMP_PLT
213         json_writer_indent_push (&writer);
214         json_writer_indent (&writer);
215         json_writer_object_key(&writer, "plt");
216         json_writer_array_begin (&writer);
217
218         for (i = 0; i < acfg->plt_offset; ++i) {
219                 MonoPltEntry *plt_entry = NULL;
220                 MonoJumpInfo *ji;
221
222                 if (i == 0)
223                         /* 
224                          * The first plt entry is unused.
225                          */
226                         continue;
227
228                 plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
229                 ji = plt_entry->ji;
230
231                 json_writer_indent (&writer);
232                 json_writer_printf (&writer, "{ ");
233                 json_writer_object_key(&writer, "symbol");
234                 json_writer_printf (&writer, "\"%s\" },\n", plt_entry->symbol);
235         }
236
237         json_writer_indent_pop (&writer);
238         json_writer_indent (&writer);
239         json_writer_array_end (&writer);
240         json_writer_printf (&writer, ",\n");
241 #endif
242
243         // GOT entries
244 #ifdef DUMP_GOT
245         json_writer_indent_push (&writer);
246         json_writer_indent (&writer);
247         json_writer_object_key(&writer, "got");
248         json_writer_array_begin (&writer);
249
250         json_writer_indent_push (&writer);
251         for (i = 0; i < acfg->got_info.got_patches->len; ++i) {
252                 MonoJumpInfo *ji = g_ptr_array_index (acfg->got_info.got_patches, i);
253
254                 json_writer_indent (&writer);
255                 json_writer_printf (&writer, "{ ");
256                 json_writer_object_key(&writer, "patch_name");
257                 json_writer_printf (&writer, "\"%s\" },\n", get_patch_name (ji->type));
258         }
259
260         json_writer_indent_pop (&writer);
261         json_writer_indent (&writer);
262         json_writer_array_end (&writer);
263         json_writer_printf (&writer, ",\n");
264 #endif
265
266         json_writer_indent_pop (&writer);
267         json_writer_indent (&writer);
268         json_writer_object_end (&writer);
269
270         dumpname = g_strdup_printf ("%s.json", g_path_get_basename (acfg->image->name));
271         dumpfile = fopen (dumpname, "w+");
272         g_free (dumpname);
273
274         fprintf (dumpfile, "%s", writer.text->str);
275         fclose (dumpfile);
276
277         json_writer_destroy (&writer);
278 }
279
280 #else
281
282 static void aot_dump (MonoAotCompile *acfg)
283 {
284
285 }
286
287 #endif