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