25a4c287d7c5284ebe0ed5d2d46e4f2e7cdedf1e
[platform/upstream/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
231   /* Functions for implementing "compile".  */
232
233   void
234   make_fake_args (auto_vec <const char *> *argvec,
235                   const char *ctxt_progname);
236
237   void
238   convert_to_dso (const char *ctxt_progname);
239
240 private:
241   ::gcc::jit::recording::context *m_recording_ctxt;
242
243   /* Allocated using xmalloc (by xstrdup).  */
244   char *m_path_template;
245
246   /* This either aliases m_path_template, or is NULL.  */
247   char *m_path_tempdir;
248
249   /* The following are allocated using xmalloc.  */
250   char *m_path_c_file;
251   char *m_path_s_file;
252   char *m_path_so_file;
253
254   auto_vec<function *> m_functions;
255   tree m_char_array_type_node;
256   tree m_const_char_ptr;
257
258   /* Source location handling.  */
259   auto_vec<source_file *> m_source_files;
260
261   auto_vec<std::pair<tree, location *> > m_cached_locations;
262 };
263
264 /* A temporary wrapper object.
265    These objects are (mostly) only valid during replay.
266    We allocate them on the GC heap, so that they will be cleaned
267    the next time the GC collects.
268    The exception is the "function" class, which is tracked and marked by
269    the jit::context, since it needs to stay alive during post-processing
270    (when the GC could run). */
271 class wrapper
272 {
273 public:
274   /* Allocate in the GC heap.  */
275   void *operator new (size_t sz);
276
277   /* Some wrapper subclasses contain vec<> and so need to
278      release them when they are GC-ed.  */
279   virtual void finalizer () { }
280
281 };
282
283 class type : public wrapper
284 {
285 public:
286   type (tree inner)
287     : m_inner(inner)
288   {}
289
290   tree as_tree () const { return m_inner; }
291
292   type *get_pointer () const { return new type (build_pointer_type (m_inner)); }
293
294   type *get_const () const
295   {
296     return new type (build_qualified_type (m_inner, TYPE_QUAL_CONST));
297   }
298
299   type *get_volatile () const
300   {
301     return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE));
302   }
303
304 private:
305   tree m_inner;
306 };
307
308 class compound_type : public type
309 {
310 public:
311   compound_type (tree inner)
312     : type (inner)
313   {}
314
315   void set_fields (const auto_vec<field *> *fields);
316 };
317
318 class field : public wrapper
319 {
320 public:
321   field (tree inner)
322     : m_inner(inner)
323   {}
324
325   tree as_tree () const { return m_inner; }
326
327 private:
328   tree m_inner;
329 };
330
331 class function : public wrapper
332 {
333 public:
334   function(context *ctxt, tree fndecl, enum gcc_jit_function_kind kind);
335
336   void gt_ggc_mx ();
337   void finalizer ();
338
339   tree get_return_type_as_tree () const;
340
341   tree as_fndecl () const { return m_inner_fndecl; }
342
343   enum gcc_jit_function_kind get_kind () const { return m_kind; }
344
345   lvalue *
346   new_local (location *loc,
347              type *type,
348              const char *name);
349
350   block*
351   new_block (const char *name);
352
353   void
354   build_stmt_list ();
355
356   void
357   postprocess ();
358
359 public:
360   context *m_ctxt;
361
362 public:
363   void
364   set_tree_location (tree t, location *loc)
365   {
366     m_ctxt->set_tree_location (t, loc);
367   }
368
369 private:
370   tree m_inner_fndecl;
371   tree m_inner_block;
372   tree m_inner_bind_expr;
373   enum gcc_jit_function_kind m_kind;
374   tree m_stmt_list;
375   tree_stmt_iterator m_stmt_iter;
376   vec<block *> m_blocks;
377 };
378
379 class block : public wrapper
380 {
381 public:
382   block (function *func,
383          const char *name);
384
385   void finalizer ();
386
387   tree as_label_decl () const { return m_label_decl; }
388
389   void
390   add_eval (location *loc,
391             rvalue *rvalue);
392
393   void
394   add_assignment (location *loc,
395                   lvalue *lvalue,
396                   rvalue *rvalue);
397
398   void
399   add_comment (location *loc,
400                const char *text);
401
402   void
403   add_conditional (location *loc,
404                    rvalue *boolval,
405                    block *on_true,
406                    block *on_false);
407
408   block *
409   add_block (location *loc,
410              const char *name);
411
412   void
413   add_jump (location *loc,
414             block *target);
415
416   void
417   add_return (location *loc,
418               rvalue *rvalue);
419
420 private:
421   void
422   set_tree_location (tree t, location *loc)
423   {
424     m_func->set_tree_location (t, loc);
425   }
426
427   void add_stmt (tree stmt)
428   {
429     /* TODO: use one stmt_list per block.  */
430     m_stmts.safe_push (stmt);
431   }
432
433 private:
434   function *m_func;
435   tree m_label_decl;
436   vec<tree> m_stmts;
437
438 public: // for now
439   tree m_label_expr;
440
441   friend class function;
442 };
443
444 class rvalue : public wrapper
445 {
446 public:
447   rvalue (context *ctxt, tree inner)
448     : m_ctxt (ctxt),
449       m_inner (inner)
450   {}
451
452   rvalue *
453   as_rvalue () { return this; }
454
455   tree as_tree () const { return m_inner; }
456
457   context *get_context () const { return m_ctxt; }
458
459   type *
460   get_type () { return new type (TREE_TYPE (m_inner)); }
461
462   rvalue *
463   access_field (location *loc,
464                 field *field);
465
466   lvalue *
467   dereference_field (location *loc,
468                      field *field);
469
470   lvalue *
471   dereference (location *loc);
472
473 private:
474   context *m_ctxt;
475   tree m_inner;
476 };
477
478 class lvalue : public rvalue
479 {
480 public:
481   lvalue (context *ctxt, tree inner)
482     : rvalue(ctxt, inner)
483   {}
484
485   lvalue *
486   as_lvalue () { return this; }
487
488   lvalue *
489   access_field (location *loc,
490                 field *field);
491
492   rvalue *
493   get_address (location *loc);
494
495 };
496
497 class param : public lvalue
498 {
499 public:
500   param (context *ctxt, tree inner)
501     : lvalue(ctxt, inner)
502   {}
503 };
504
505 /* Dealing with the linemap API.
506
507    It appears that libcpp requires locations to be created as if by
508    a tokenizer, creating them by filename, in ascending order of
509    line/column, whereas our API doesn't impose any such constraints:
510    we allow client code to create locations in arbitrary orders.
511
512    To square this circle, we need to cache all location creation,
513    grouping things up by filename/line, and then creating the linemap
514    entries in a post-processing phase.  */
515
516 /* A set of locations, all sharing a filename */
517 class source_file : public wrapper
518 {
519 public:
520   source_file (tree filename);
521   void finalizer ();
522
523   source_line *
524   get_source_line (int line_num);
525
526   tree filename_as_tree () const { return m_filename; }
527
528   const char*
529   get_filename () const { return IDENTIFIER_POINTER (m_filename); }
530
531   vec<source_line *> m_source_lines;
532
533 private:
534   tree m_filename;
535 };
536
537 /* A source line, with one or more locations of interest.  */
538 class source_line : public wrapper
539 {
540 public:
541   source_line (source_file *file, int line_num);
542   void finalizer ();
543
544   location *
545   get_location (recording::location *rloc, int column_num);
546
547   int get_line_num () const { return m_line_num; }
548
549   vec<location *> m_locations;
550
551 private:
552   source_file *m_source_file;
553   int m_line_num;
554 };
555
556 /* A specific location on a source line.  This is what we expose
557    to the client API.  */
558 class location : public wrapper
559 {
560 public:
561   location (recording::location *loc, source_line *line, int column_num);
562
563   int get_column_num () const { return m_column_num; }
564
565   recording::location *get_recording_loc () const { return m_recording_loc; }
566
567   source_location m_srcloc;
568
569 private:
570   recording::location *m_recording_loc;
571   source_line *m_line;
572   int m_column_num;
573 };
574
575 } // namespace gcc::jit::playback
576
577 extern playback::context *active_playback_ctxt;
578
579 } // namespace gcc::jit
580
581 } // namespace gcc
582
583 #endif /* JIT_PLAYBACK_H */
584