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