Move gcc_jit_result implementation to a new files jit-result.{h|c}
[gcc.git] / gcc / jit / jit-playback.h
1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #ifndef JIT_PLAYBACK_H
22 #define JIT_PLAYBACK_H
23
24 #include <utility> // for std::pair
25
26 #include "jit-recording.h"
27
28 namespace gcc {
29
30 namespace jit {
31
32 /**********************************************************************
33 Playback.
34 **********************************************************************/
35
36 namespace playback {
37
38 class context
39 {
40 public:
41 context (::gcc::jit::recording::context *ctxt);
42 ~context ();
43
44 void gt_ggc_mx ();
45
46 void replay ();
47
48 location *
49 new_location (recording::location *rloc,
50 const char *filename,
51 int line,
52 int column);
53
54 type *
55 get_type (enum gcc_jit_types type);
56
57 type *
58 new_array_type (location *loc,
59 type *element_type,
60 int num_elements);
61
62 field *
63 new_field (location *loc,
64 type *type,
65 const char *name);
66
67 compound_type *
68 new_compound_type (location *loc,
69 const char *name,
70 bool is_struct); /* else is union */
71
72 type *
73 new_function_type (type *return_type,
74 const auto_vec<type *> *param_types,
75 int is_variadic);
76
77 param *
78 new_param (location *loc,
79 type *type,
80 const char *name);
81
82 function *
83 new_function (location *loc,
84 enum gcc_jit_function_kind kind,
85 type *return_type,
86 const char *name,
87 const auto_vec<param *> *params,
88 int is_variadic,
89 enum built_in_function builtin_id);
90
91 lvalue *
92 new_global (location *loc,
93 type *type,
94 const char *name);
95
96 rvalue *
97 new_rvalue_from_int (type *type,
98 int value);
99
100 rvalue *
101 new_rvalue_from_double (type *type,
102 double value);
103
104 rvalue *
105 new_rvalue_from_ptr (type *type,
106 void *value);
107
108 rvalue *
109 new_string_literal (const char *value);
110
111 rvalue *
112 new_unary_op (location *loc,
113 enum gcc_jit_unary_op op,
114 type *result_type,
115 rvalue *a);
116
117 rvalue *
118 new_binary_op (location *loc,
119 enum gcc_jit_binary_op op,
120 type *result_type,
121 rvalue *a, rvalue *b);
122
123 rvalue *
124 new_comparison (location *loc,
125 enum gcc_jit_comparison op,
126 rvalue *a, rvalue *b);
127
128 rvalue *
129 new_call (location *loc,
130 function *func,
131 const auto_vec<rvalue *> *args);
132
133 rvalue *
134 new_call_through_ptr (location *loc,
135 rvalue *fn_ptr,
136 const auto_vec<rvalue *> *args);
137
138 rvalue *
139 new_cast (location *loc,
140 rvalue *expr,
141 type *type_);
142
143 lvalue *
144 new_array_access (location *loc,
145 rvalue *ptr,
146 rvalue *index);
147
148 void
149 set_str_option (enum gcc_jit_str_option opt,
150 const char *value);
151
152 void
153 set_int_option (enum gcc_jit_int_option opt,
154 int value);
155
156 void
157 set_bool_option (enum gcc_jit_bool_option opt,
158 int value);
159
160 const char *
161 get_str_option (enum gcc_jit_str_option opt) const
162 {
163 return m_recording_ctxt->get_str_option (opt);
164 }
165
166 int
167 get_int_option (enum gcc_jit_int_option opt) const
168 {
169 return m_recording_ctxt->get_int_option (opt);
170 }
171
172 int
173 get_bool_option (enum gcc_jit_bool_option opt) const
174 {
175 return m_recording_ctxt->get_bool_option (opt);
176 }
177
178 result *
179 compile ();
180
181 void
182 add_error (location *loc, const char *fmt, ...)
183 GNU_PRINTF(3, 4);
184
185 void
186 add_error_va (location *loc, const char *fmt, va_list ap)
187 GNU_PRINTF(3, 0);
188
189 const char *
190 get_first_error () const;
191
192 void
193 set_tree_location (tree t, location *loc);
194
195 tree
196 new_field_access (location *loc,
197 tree datum,
198 field *field);
199
200 tree
201 new_dereference (tree ptr, location *loc);
202
203 tree
204 as_truth_value (tree expr, location *loc);
205
206 bool errors_occurred () const
207 {
208 return m_recording_ctxt->errors_occurred ();
209 }
210
211 private:
212 void dump_generated_code ();
213
214 rvalue *
215 build_call (location *loc,
216 tree fn_ptr,
217 const auto_vec<rvalue *> *args);
218
219 tree
220 build_cast (location *loc,
221 rvalue *expr,
222 type *type_);
223
224 source_file *
225 get_source_file (const char *filename);
226
227 void handle_locations ();
228
229 private:
230 ::gcc::jit::recording::context *m_recording_ctxt;
231
232 /* Allocated using xmalloc (by xstrdup). */
233 char *m_path_template;
234
235 /* This either aliases m_path_template, or is NULL. */
236 char *m_path_tempdir;
237
238 /* The following are allocated using xmalloc. */
239 char *m_path_c_file;
240 char *m_path_s_file;
241 char *m_path_so_file;
242
243 auto_vec<function *> m_functions;
244 tree m_char_array_type_node;
245 tree m_const_char_ptr;
246
247 /* Source location handling. */
248 auto_vec<source_file *> m_source_files;
249
250 auto_vec<std::pair<tree, location *> > m_cached_locations;
251 };
252
253 /* A temporary wrapper object.
254 These objects are (mostly) only valid during replay.
255 We allocate them on the GC heap, so that they will be cleaned
256 the next time the GC collects.
257 The exception is the "function" class, which is tracked and marked by
258 the jit::context, since it needs to stay alive during post-processing
259 (when the GC could run). */
260 class wrapper
261 {
262 public:
263 /* Allocate in the GC heap. */
264 void *operator new (size_t sz);
265
266 /* Some wrapper subclasses contain vec<> and so need to
267 release them when they are GC-ed. */
268 virtual void finalizer () { }
269
270 };
271
272 class type : public wrapper
273 {
274 public:
275 type (tree inner)
276 : m_inner(inner)
277 {}
278
279 tree as_tree () const { return m_inner; }
280
281 type *get_pointer () const { return new type (build_pointer_type (m_inner)); }
282
283 type *get_const () const
284 {
285 return new type (build_qualified_type (m_inner, TYPE_QUAL_CONST));
286 }
287
288 type *get_volatile () const
289 {
290 return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE));
291 }
292
293 private:
294 tree m_inner;
295 };
296
297 class compound_type : public type
298 {
299 public:
300 compound_type (tree inner)
301 : type (inner)
302 {}
303
304 void set_fields (const auto_vec<field *> *fields);
305 };
306
307 class field : public wrapper
308 {
309 public:
310 field (tree inner)
311 : m_inner(inner)
312 {}
313
314 tree as_tree () const { return m_inner; }
315
316 private:
317 tree m_inner;
318 };
319
320 class function : public wrapper
321 {
322 public:
323 function(context *ctxt, tree fndecl, enum gcc_jit_function_kind kind);
324
325 void gt_ggc_mx ();
326 void finalizer ();
327
328 tree get_return_type_as_tree () const;
329
330 tree as_fndecl () const { return m_inner_fndecl; }
331
332 enum gcc_jit_function_kind get_kind () const { return m_kind; }
333
334 lvalue *
335 new_local (location *loc,
336 type *type,
337 const char *name);
338
339 block*
340 new_block (const char *name);
341
342 void
343 build_stmt_list ();
344
345 void
346 postprocess ();
347
348 public:
349 context *m_ctxt;
350
351 public:
352 void
353 set_tree_location (tree t, location *loc)
354 {
355 m_ctxt->set_tree_location (t, loc);
356 }
357
358 private:
359 tree m_inner_fndecl;
360 tree m_inner_block;
361 tree m_inner_bind_expr;
362 enum gcc_jit_function_kind m_kind;
363 tree m_stmt_list;
364 tree_stmt_iterator m_stmt_iter;
365 vec<block *> m_blocks;
366 };
367
368 class block : public wrapper
369 {
370 public:
371 block (function *func,
372 const char *name);
373
374 void finalizer ();
375
376 tree as_label_decl () const { return m_label_decl; }
377
378 void
379 add_eval (location *loc,
380 rvalue *rvalue);
381
382 void
383 add_assignment (location *loc,
384 lvalue *lvalue,
385 rvalue *rvalue);
386
387 void
388 add_comment (location *loc,
389 const char *text);
390
391 void
392 add_conditional (location *loc,
393 rvalue *boolval,
394 block *on_true,
395 block *on_false);
396
397 block *
398 add_block (location *loc,
399 const char *name);
400
401 void
402 add_jump (location *loc,
403 block *target);
404
405 void
406 add_return (location *loc,
407 rvalue *rvalue);
408
409 private:
410 void
411 set_tree_location (tree t, location *loc)
412 {
413 m_func->set_tree_location (t, loc);
414 }
415
416 void add_stmt (tree stmt)
417 {
418 /* TODO: use one stmt_list per block. */
419 m_stmts.safe_push (stmt);
420 }
421
422 private:
423 function *m_func;
424 tree m_label_decl;
425 vec<tree> m_stmts;
426
427 public: // for now
428 tree m_label_expr;
429
430 friend class function;
431 };
432
433 class rvalue : public wrapper
434 {
435 public:
436 rvalue (context *ctxt, tree inner)
437 : m_ctxt (ctxt),
438 m_inner (inner)
439 {}
440
441 rvalue *
442 as_rvalue () { return this; }
443
444 tree as_tree () const { return m_inner; }
445
446 context *get_context () const { return m_ctxt; }
447
448 type *
449 get_type () { return new type (TREE_TYPE (m_inner)); }
450
451 rvalue *
452 access_field (location *loc,
453 field *field);
454
455 lvalue *
456 dereference_field (location *loc,
457 field *field);
458
459 lvalue *
460 dereference (location *loc);
461
462 private:
463 context *m_ctxt;
464 tree m_inner;
465 };
466
467 class lvalue : public rvalue
468 {
469 public:
470 lvalue (context *ctxt, tree inner)
471 : rvalue(ctxt, inner)
472 {}
473
474 lvalue *
475 as_lvalue () { return this; }
476
477 lvalue *
478 access_field (location *loc,
479 field *field);
480
481 rvalue *
482 get_address (location *loc);
483
484 };
485
486 class param : public lvalue
487 {
488 public:
489 param (context *ctxt, tree inner)
490 : lvalue(ctxt, inner)
491 {}
492 };
493
494 /* Dealing with the linemap API.
495
496 It appears that libcpp requires locations to be created as if by
497 a tokenizer, creating them by filename, in ascending order of
498 line/column, whereas our API doesn't impose any such constraints:
499 we allow client code to create locations in arbitrary orders.
500
501 To square this circle, we need to cache all location creation,
502 grouping things up by filename/line, and then creating the linemap
503 entries in a post-processing phase. */
504
505 /* A set of locations, all sharing a filename */
506 class source_file : public wrapper
507 {
508 public:
509 source_file (tree filename);
510 void finalizer ();
511
512 source_line *
513 get_source_line (int line_num);
514
515 tree filename_as_tree () const { return m_filename; }
516
517 const char*
518 get_filename () const { return IDENTIFIER_POINTER (m_filename); }
519
520 vec<source_line *> m_source_lines;
521
522 private:
523 tree m_filename;
524 };
525
526 /* A source line, with one or more locations of interest. */
527 class source_line : public wrapper
528 {
529 public:
530 source_line (source_file *file, int line_num);
531 void finalizer ();
532
533 location *
534 get_location (recording::location *rloc, int column_num);
535
536 int get_line_num () const { return m_line_num; }
537
538 vec<location *> m_locations;
539
540 private:
541 source_file *m_source_file;
542 int m_line_num;
543 };
544
545 /* A specific location on a source line. This is what we expose
546 to the client API. */
547 class location : public wrapper
548 {
549 public:
550 location (recording::location *loc, source_line *line, int column_num);
551
552 int get_column_num () const { return m_column_num; }
553
554 recording::location *get_recording_loc () const { return m_recording_loc; }
555
556 source_location m_srcloc;
557
558 private:
559 recording::location *m_recording_loc;
560 source_line *m_line;
561 int m_column_num;
562 };
563
564 } // namespace gcc::jit::playback
565
566 extern playback::context *active_playback_ctxt;
567
568 } // namespace gcc::jit
569
570 } // namespace gcc
571
572 #endif /* JIT_PLAYBACK_H */
573