]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/jit/jit-playback.h
Update copyright years.
[thirdparty/gcc.git] / gcc / jit / jit-playback.h
1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2019 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 "timevar.h"
27
28 #include "jit-recording.h"
29
30 struct diagnostic_context;
31 struct diagnostic_info;
32
33 namespace gcc {
34
35 namespace jit {
36
37 /**********************************************************************
38 Playback.
39 **********************************************************************/
40
41 namespace playback {
42
43 /* playback::context is an abstract base class.
44
45 The two concrete subclasses are:
46 - playback::compile_to_memory
47 - playback::compile_to_file. */
48
49 class context : public log_user
50 {
51 public:
52 context (::gcc::jit::recording::context *ctxt);
53 ~context ();
54
55 void gt_ggc_mx ();
56
57 void replay ();
58
59 location *
60 new_location (recording::location *rloc,
61 const char *filename,
62 int line,
63 int column);
64
65 type *
66 get_type (enum gcc_jit_types type);
67
68 type *
69 new_array_type (location *loc,
70 type *element_type,
71 int num_elements);
72
73 field *
74 new_field (location *loc,
75 type *type,
76 const char *name);
77
78 compound_type *
79 new_compound_type (location *loc,
80 const char *name,
81 bool is_struct); /* else is union */
82
83 type *
84 new_function_type (type *return_type,
85 const auto_vec<type *> *param_types,
86 int is_variadic);
87
88 param *
89 new_param (location *loc,
90 type *type,
91 const char *name);
92
93 function *
94 new_function (location *loc,
95 enum gcc_jit_function_kind kind,
96 type *return_type,
97 const char *name,
98 const auto_vec<param *> *params,
99 int is_variadic,
100 enum built_in_function builtin_id);
101
102 lvalue *
103 new_global (location *loc,
104 enum gcc_jit_global_kind kind,
105 type *type,
106 const char *name);
107
108 template <typename HOST_TYPE>
109 rvalue *
110 new_rvalue_from_const (type *type,
111 HOST_TYPE value);
112
113 rvalue *
114 new_string_literal (const char *value);
115
116 rvalue *
117 new_rvalue_from_vector (location *loc,
118 type *type,
119 const auto_vec<rvalue *> &elements);
120
121 rvalue *
122 new_unary_op (location *loc,
123 enum gcc_jit_unary_op op,
124 type *result_type,
125 rvalue *a);
126
127 rvalue *
128 new_binary_op (location *loc,
129 enum gcc_jit_binary_op op,
130 type *result_type,
131 rvalue *a, rvalue *b);
132
133 rvalue *
134 new_comparison (location *loc,
135 enum gcc_jit_comparison op,
136 rvalue *a, rvalue *b);
137
138 rvalue *
139 new_call (location *loc,
140 function *func,
141 const auto_vec<rvalue *> *args,
142 bool require_tail_call);
143
144 rvalue *
145 new_call_through_ptr (location *loc,
146 rvalue *fn_ptr,
147 const auto_vec<rvalue *> *args,
148 bool require_tail_call);
149
150 rvalue *
151 new_cast (location *loc,
152 rvalue *expr,
153 type *type_);
154
155 lvalue *
156 new_array_access (location *loc,
157 rvalue *ptr,
158 rvalue *index);
159
160 void
161 set_str_option (enum gcc_jit_str_option opt,
162 const char *value);
163
164 void
165 set_int_option (enum gcc_jit_int_option opt,
166 int value);
167
168 void
169 set_bool_option (enum gcc_jit_bool_option opt,
170 int value);
171
172 const char *
173 get_str_option (enum gcc_jit_str_option opt) const
174 {
175 return m_recording_ctxt->get_str_option (opt);
176 }
177
178 int
179 get_int_option (enum gcc_jit_int_option opt) const
180 {
181 return m_recording_ctxt->get_int_option (opt);
182 }
183
184 int
185 get_bool_option (enum gcc_jit_bool_option opt) const
186 {
187 return m_recording_ctxt->get_bool_option (opt);
188 }
189
190 int
191 get_inner_bool_option (enum inner_bool_option opt) const
192 {
193 return m_recording_ctxt->get_inner_bool_option (opt);
194 }
195
196 builtins_manager *get_builtins_manager () const
197 {
198 return m_recording_ctxt->get_builtins_manager ();
199 }
200
201 void
202 compile ();
203
204 void
205 add_error (location *loc, const char *fmt, ...)
206 GNU_PRINTF(3, 4);
207
208 void
209 add_error_va (location *loc, const char *fmt, va_list ap)
210 GNU_PRINTF(3, 0);
211
212 const char *
213 get_first_error () const;
214
215 void
216 add_diagnostic (struct diagnostic_context *context,
217 struct diagnostic_info *diagnostic);
218
219 void
220 set_tree_location (tree t, location *loc);
221
222 tree
223 new_field_access (location *loc,
224 tree datum,
225 field *field);
226
227 tree
228 new_dereference (tree ptr, location *loc);
229
230 tree
231 as_truth_value (tree expr, location *loc);
232
233 bool errors_occurred () const
234 {
235 return m_recording_ctxt->errors_occurred ();
236 }
237
238 timer *get_timer () const { return m_recording_ctxt->get_timer (); }
239
240 private:
241 void dump_generated_code ();
242
243 rvalue *
244 build_call (location *loc,
245 tree fn_ptr,
246 const auto_vec<rvalue *> *args,
247 bool require_tail_call);
248
249 tree
250 build_cast (location *loc,
251 rvalue *expr,
252 type *type_);
253
254 source_file *
255 get_source_file (const char *filename);
256
257 void handle_locations ();
258
259 const char * get_path_c_file () const;
260 const char * get_path_s_file () const;
261 const char * get_path_so_file () const;
262
263 private:
264
265 /* Functions for implementing "compile". */
266
267 void acquire_mutex ();
268 void release_mutex ();
269
270 void
271 make_fake_args (vec <char *> *argvec,
272 const char *ctxt_progname,
273 vec <recording::requested_dump> *requested_dumps);
274
275 void
276 extract_any_requested_dumps
277 (vec <recording::requested_dump> *requested_dumps);
278
279 char *
280 read_dump_file (const char *path);
281
282 virtual void postprocess (const char *ctxt_progname) = 0;
283
284 protected:
285 tempdir *get_tempdir () { return m_tempdir; }
286
287 void
288 convert_to_dso (const char *ctxt_progname);
289
290 void
291 invoke_driver (const char *ctxt_progname,
292 const char *input_file,
293 const char *output_file,
294 timevar_id_t tv_id,
295 bool shared,
296 bool run_linker);
297
298 void
299 add_multilib_driver_arguments (vec <char *> *argvec);
300
301 result *
302 dlopen_built_dso ();
303
304 private:
305 void
306 invoke_embedded_driver (const vec <char *> *argvec);
307
308 void
309 invoke_external_driver (const char *ctxt_progname,
310 vec <char *> *argvec);
311
312 private:
313 ::gcc::jit::recording::context *m_recording_ctxt;
314
315 tempdir *m_tempdir;
316
317 auto_vec<function *> m_functions;
318 auto_vec<tree> m_globals;
319 tree m_char_array_type_node;
320 tree m_const_char_ptr;
321
322 /* Source location handling. */
323 auto_vec<source_file *> m_source_files;
324
325 auto_vec<std::pair<tree, location *> > m_cached_locations;
326 };
327
328 class compile_to_memory : public context
329 {
330 public:
331 compile_to_memory (recording::context *ctxt);
332 void postprocess (const char *ctxt_progname) FINAL OVERRIDE;
333
334 result *get_result_obj () const { return m_result; }
335
336 private:
337 result *m_result;
338 };
339
340 class compile_to_file : public context
341 {
342 public:
343 compile_to_file (recording::context *ctxt,
344 enum gcc_jit_output_kind output_kind,
345 const char *output_path);
346 void postprocess (const char *ctxt_progname) FINAL OVERRIDE;
347
348 private:
349 void
350 copy_file (const char *src_path,
351 const char *dst_path);
352
353 private:
354 enum gcc_jit_output_kind m_output_kind;
355 const char *m_output_path;
356 };
357
358
359 /* A temporary wrapper object.
360 These objects are (mostly) only valid during replay.
361 We allocate them on the GC heap, so that they will be cleaned
362 the next time the GC collects.
363 The exception is the "function" class, which is tracked and marked by
364 the jit::context, since it needs to stay alive during post-processing
365 (when the GC could run). */
366 class wrapper
367 {
368 public:
369 /* Allocate in the GC heap. */
370 void *operator new (size_t sz);
371
372 /* Some wrapper subclasses contain vec<> and so need to
373 release them when they are GC-ed. */
374 virtual void finalizer () { }
375
376 };
377
378 class type : public wrapper
379 {
380 public:
381 type (tree inner)
382 : m_inner(inner)
383 {}
384
385 tree as_tree () const { return m_inner; }
386
387 type *get_pointer () const { return new type (build_pointer_type (m_inner)); }
388
389 type *get_const () const
390 {
391 return new type (build_qualified_type (m_inner, TYPE_QUAL_CONST));
392 }
393
394 type *get_volatile () const
395 {
396 return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE));
397 }
398
399 type *get_aligned (size_t alignment_in_bytes) const;
400 type *get_vector (size_t num_units) const;
401
402 private:
403 tree m_inner;
404 };
405
406 class compound_type : public type
407 {
408 public:
409 compound_type (tree inner)
410 : type (inner)
411 {}
412
413 void set_fields (const auto_vec<field *> *fields);
414 };
415
416 class field : public wrapper
417 {
418 public:
419 field (tree inner)
420 : m_inner(inner)
421 {}
422
423 tree as_tree () const { return m_inner; }
424
425 private:
426 tree m_inner;
427 };
428
429 class function : public wrapper
430 {
431 public:
432 function(context *ctxt, tree fndecl, enum gcc_jit_function_kind kind);
433
434 void gt_ggc_mx ();
435 void finalizer () FINAL OVERRIDE;
436
437 tree get_return_type_as_tree () const;
438
439 tree as_fndecl () const { return m_inner_fndecl; }
440
441 enum gcc_jit_function_kind get_kind () const { return m_kind; }
442
443 lvalue *
444 new_local (location *loc,
445 type *type,
446 const char *name);
447
448 block*
449 new_block (const char *name);
450
451 rvalue *
452 get_address (location *loc);
453
454 void
455 build_stmt_list ();
456
457 void
458 postprocess ();
459
460 public:
461 context *m_ctxt;
462
463 public:
464 void
465 set_tree_location (tree t, location *loc)
466 {
467 m_ctxt->set_tree_location (t, loc);
468 }
469
470 private:
471 tree m_inner_fndecl;
472 tree m_inner_block;
473 tree m_inner_bind_expr;
474 enum gcc_jit_function_kind m_kind;
475 tree m_stmt_list;
476 tree_stmt_iterator m_stmt_iter;
477 vec<block *> m_blocks;
478 };
479
480 struct case_
481 {
482 case_ (rvalue *min_value, rvalue *max_value, block *dest_block)
483 : m_min_value (min_value),
484 m_max_value (max_value),
485 m_dest_block (dest_block)
486 {}
487
488 rvalue *m_min_value;
489 rvalue *m_max_value;
490 block *m_dest_block;
491 };
492
493 class block : public wrapper
494 {
495 public:
496 block (function *func,
497 const char *name);
498
499 void finalizer () FINAL OVERRIDE;
500
501 tree as_label_decl () const { return m_label_decl; }
502
503 function *get_function () const { return m_func; }
504
505 void
506 add_eval (location *loc,
507 rvalue *rvalue);
508
509 void
510 add_assignment (location *loc,
511 lvalue *lvalue,
512 rvalue *rvalue);
513
514 void
515 add_comment (location *loc,
516 const char *text);
517
518 void
519 add_conditional (location *loc,
520 rvalue *boolval,
521 block *on_true,
522 block *on_false);
523
524 block *
525 add_block (location *loc,
526 const char *name);
527
528 void
529 add_jump (location *loc,
530 block *target);
531
532 void
533 add_return (location *loc,
534 rvalue *rvalue);
535
536 void
537 add_switch (location *loc,
538 rvalue *expr,
539 block *default_block,
540 const auto_vec <case_> *cases);
541
542 private:
543 void
544 set_tree_location (tree t, location *loc)
545 {
546 m_func->set_tree_location (t, loc);
547 }
548
549 void add_stmt (tree stmt)
550 {
551 /* TODO: use one stmt_list per block. */
552 m_stmts.safe_push (stmt);
553 }
554
555 private:
556 function *m_func;
557 tree m_label_decl;
558 vec<tree> m_stmts;
559
560 public: // for now
561 tree m_label_expr;
562
563 friend class function;
564 };
565
566 class rvalue : public wrapper
567 {
568 public:
569 rvalue (context *ctxt, tree inner)
570 : m_ctxt (ctxt),
571 m_inner (inner)
572 {}
573
574 rvalue *
575 as_rvalue () { return this; }
576
577 tree as_tree () const { return m_inner; }
578
579 context *get_context () const { return m_ctxt; }
580
581 type *
582 get_type () { return new type (TREE_TYPE (m_inner)); }
583
584 rvalue *
585 access_field (location *loc,
586 field *field);
587
588 lvalue *
589 dereference_field (location *loc,
590 field *field);
591
592 lvalue *
593 dereference (location *loc);
594
595 private:
596 context *m_ctxt;
597 tree m_inner;
598 };
599
600 class lvalue : public rvalue
601 {
602 public:
603 lvalue (context *ctxt, tree inner)
604 : rvalue(ctxt, inner)
605 {}
606
607 lvalue *
608 as_lvalue () { return this; }
609
610 lvalue *
611 access_field (location *loc,
612 field *field);
613
614 rvalue *
615 get_address (location *loc);
616
617 };
618
619 class param : public lvalue
620 {
621 public:
622 param (context *ctxt, tree inner)
623 : lvalue(ctxt, inner)
624 {}
625 };
626
627 /* Dealing with the linemap API.
628
629 It appears that libcpp requires locations to be created as if by
630 a tokenizer, creating them by filename, in ascending order of
631 line/column, whereas our API doesn't impose any such constraints:
632 we allow client code to create locations in arbitrary orders.
633
634 To square this circle, we need to cache all location creation,
635 grouping things up by filename/line, and then creating the linemap
636 entries in a post-processing phase. */
637
638 /* A set of locations, all sharing a filename */
639 class source_file : public wrapper
640 {
641 public:
642 source_file (tree filename);
643 void finalizer () FINAL OVERRIDE;
644
645 source_line *
646 get_source_line (int line_num);
647
648 tree filename_as_tree () const { return m_filename; }
649
650 const char*
651 get_filename () const { return IDENTIFIER_POINTER (m_filename); }
652
653 vec<source_line *> m_source_lines;
654
655 private:
656 tree m_filename;
657 };
658
659 /* A source line, with one or more locations of interest. */
660 class source_line : public wrapper
661 {
662 public:
663 source_line (source_file *file, int line_num);
664 void finalizer () FINAL OVERRIDE;
665
666 location *
667 get_location (recording::location *rloc, int column_num);
668
669 int get_line_num () const { return m_line_num; }
670
671 vec<location *> m_locations;
672
673 private:
674 source_file *m_source_file;
675 int m_line_num;
676 };
677
678 /* A specific location on a source line. This is what we expose
679 to the client API. */
680 class location : public wrapper
681 {
682 public:
683 location (recording::location *loc, source_line *line, int column_num);
684
685 int get_column_num () const { return m_column_num; }
686
687 recording::location *get_recording_loc () const { return m_recording_loc; }
688
689 location_t m_srcloc;
690
691 private:
692 recording::location *m_recording_loc;
693 source_line *m_line;
694 int m_column_num;
695 };
696
697 } // namespace gcc::jit::playback
698
699 extern playback::context *active_playback_ctxt;
700
701 } // namespace gcc::jit
702
703 } // namespace gcc
704
705 #endif /* JIT_PLAYBACK_H */
706