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