1 /* A C++ API for libgccjit, purely as inline wrapper functions.
2    Copyright (C) 2014-2019 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10 
11 GCC is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef LIBGCCJIT_PLUS_PLUS_H
21 #define LIBGCCJIT_PLUS_PLUS_H
22 
23 #include "libgccjit.h"
24 
25 #include <limits>
26 #include <ostream>
27 #include <vector>
28 
29 /****************************************************************************
30  C++ API
31  ****************************************************************************/
32 
33 namespace gccjit
34 {
35   /* Indentation indicates inheritance.  */
36   class context;
37   class error;
38   class object;
39     class location;
40     class field;
41     class type;
42       class struct_;
43     class function;
44     class block;
45     class rvalue;
46      class lvalue;
47        class param;
48     class case_;
49   class timer;
50   class auto_time;
51 
52   /* Errors within the API become C++ exceptions of this class.  */
53   class error
54   {
55   };
56 
57   class object
58   {
59   public:
60     context get_context () const;
61 
62     std::string get_debug_string () const;
63 
64   protected:
65     object ();
66     object (gcc_jit_object *obj);
67 
68     gcc_jit_object *get_inner_object () const;
69 
70   private:
71     gcc_jit_object *m_inner_obj;
72   };
73 
74   inline std::ostream& operator << (std::ostream& stream, const object &obj);
75 
76   /* Some client code will want to supply source code locations, others
77      won't.  To avoid doubling the number of entrypoints, everything
78      accepting a location also has a default argument.  To do this, the
79      other classes need to see that "location" has a default constructor,
80      hence we need to declare it first.  */
81   class location : public object
82   {
83   public:
84     location ();
85     location (gcc_jit_location *loc);
86 
87     gcc_jit_location *get_inner_location () const;
88   };
89 
90   class context
91   {
92   public:
93     static context acquire ();
94     context ();
95     context (gcc_jit_context *ctxt);
96 
97     gccjit::context new_child_context ();
98 
get_inner_context()99     gcc_jit_context *get_inner_context () { return m_inner_ctxt; }
100 
101     void release ();
102 
103     gcc_jit_result *compile ();
104 
105     void compile_to_file (enum gcc_jit_output_kind output_kind,
106 			  const char *output_path);
107 
108     void dump_to_file (const std::string &path,
109 		       bool update_locations);
110 
111     void set_logfile (FILE *logfile,
112 		      int flags,
113 		      int verbosity);
114 
115     void dump_reproducer_to_file (const char *path);
116 
117     void set_str_option (enum gcc_jit_str_option opt,
118 			 const char *value);
119 
120     void set_int_option (enum gcc_jit_int_option opt,
121 			 int value);
122 
123     void set_bool_option (enum gcc_jit_bool_option opt,
124 			  int value);
125 
126     void set_bool_allow_unreachable_blocks (int bool_value);
127     void set_bool_use_external_driver (int bool_value);
128 
129     void add_command_line_option (const char *optname);
130     void add_driver_option (const char *optname);
131 
132     void set_timer (gccjit::timer t);
133     gccjit::timer get_timer () const;
134 
135     location
136     new_location (const std::string &filename,
137 		  int line,
138 		  int column);
139 
140     type get_type (enum gcc_jit_types kind);
141     type get_int_type (size_t num_bytes, int is_signed);
142 
143     /* A way to map a specific int type, using the compiler to
144        get the details automatically e.g.:
145 	  gccjit::type type = get_int_type <my_int_type_t> ();  */
146     template <typename T>
147     type get_int_type ();
148 
149     type new_array_type (type element_type, int num_elements,
150 			 location loc = location ());
151 
152     field new_field (type type_, const std::string &name,
153 		     location loc = location ());
154 
155     struct_ new_struct_type (const std::string &name,
156 			     std::vector<field> &fields,
157 			     location loc = location ());
158 
159     struct_ new_opaque_struct_type (const std::string &name,
160 				    location loc = location ());
161 
162     param new_param (type type_,
163 		     const std::string &name,
164 		     location loc = location ());
165 
166     function new_function (enum gcc_jit_function_kind kind,
167 			   type return_type,
168 			   const std::string &name,
169 			   std::vector<param> &params,
170 			   int is_variadic,
171 			   location loc = location ());
172 
173     function get_builtin_function (const std::string &name);
174 
175     lvalue new_global (enum gcc_jit_global_kind kind,
176 		       type type_,
177 		       const std::string &name,
178 		       location loc = location ());
179 
180     rvalue new_rvalue (type numeric_type,
181 		       int value) const;
182     rvalue new_rvalue (type numeric_type,
183 		       long value) const;
184     rvalue zero (type numeric_type) const;
185     rvalue one (type numeric_type) const;
186     rvalue new_rvalue (type numeric_type,
187 		       double value) const;
188     rvalue new_rvalue (type pointer_type,
189 		       void *value) const;
190     rvalue new_rvalue (const std::string &value) const;
191     rvalue new_rvalue (type vector_type,
192 		       std::vector<rvalue> elements) const;
193 
194     /* Generic unary operations...  */
195     rvalue new_unary_op (enum gcc_jit_unary_op op,
196 			 type result_type,
197 			 rvalue a,
198 			 location loc = location ());
199 
200     /* ...and shorter ways to spell the various specific kinds of
201        unary op.  */
202     rvalue new_minus (type result_type,
203 		      rvalue a,
204 		      location loc = location ());
205     rvalue new_bitwise_negate (type result_type,
206 			       rvalue a,
207 			       location loc = location ());
208     rvalue new_logical_negate (type result_type,
209 			       rvalue a,
210 			       location loc = location ());
211 
212     /* Generic binary operations...  */
213     rvalue new_binary_op (enum gcc_jit_binary_op op,
214 			  type result_type,
215 			  rvalue a, rvalue b,
216 			  location loc = location ());
217 
218     /* ...and shorter ways to spell the various specific kinds of
219        binary op.  */
220     rvalue new_plus (type result_type,
221 		     rvalue a, rvalue b,
222 		     location loc = location ());
223     rvalue new_minus (type result_type,
224 		      rvalue a, rvalue b,
225 		      location loc = location ());
226     rvalue new_mult (type result_type,
227 		     rvalue a, rvalue b,
228 		     location loc = location ());
229     rvalue new_divide (type result_type,
230 		       rvalue a, rvalue b,
231 		       location loc = location ());
232     rvalue new_modulo (type result_type,
233 		       rvalue a, rvalue b,
234 		       location loc = location ());
235     rvalue new_bitwise_and (type result_type,
236 			    rvalue a, rvalue b,
237 			    location loc = location ());
238     rvalue new_bitwise_xor (type result_type,
239 			    rvalue a, rvalue b,
240 			    location loc = location ());
241     rvalue new_bitwise_or (type result_type,
242 			   rvalue a, rvalue b,
243 			   location loc = location ());
244     rvalue new_logical_and (type result_type,
245 			    rvalue a, rvalue b,
246 			    location loc = location ());
247     rvalue new_logical_or (type result_type,
248 			   rvalue a, rvalue b,
249 			   location loc = location ());
250 
251     /* Generic comparisons...  */
252     rvalue new_comparison (enum gcc_jit_comparison op,
253 			   rvalue a, rvalue b,
254 			   location loc = location ());
255     /* ...and shorter ways to spell the various specific kinds of
256        comparison.  */
257     rvalue new_eq (rvalue a, rvalue b,
258 		   location loc = location ());
259     rvalue new_ne (rvalue a, rvalue b,
260 		   location loc = location ());
261     rvalue new_lt (rvalue a, rvalue b,
262 		   location loc = location ());
263     rvalue new_le (rvalue a, rvalue b,
264 		   location loc = location ());
265     rvalue new_gt (rvalue a, rvalue b,
266 		   location loc = location ());
267     rvalue new_ge (rvalue a, rvalue b,
268 		   location loc = location ());
269 
270     /* The most general way of creating a function call.  */
271     rvalue new_call (function func,
272 		     std::vector<rvalue> &args,
273 		     location loc = location ());
274 
275     /* In addition, we provide a series of overloaded "new_call" methods
276        for specific numbers of args (from 0 - 6), to avoid the need for
277        client code to manually build a vector.  */
278     rvalue new_call (function func,
279 		     location loc = location ());
280     rvalue new_call (function func,
281 		     rvalue arg0,
282 		     location loc = location ());
283     rvalue new_call (function func,
284 		     rvalue arg0, rvalue arg1,
285 		     location loc = location ());
286     rvalue new_call (function func,
287 		     rvalue arg0, rvalue arg1, rvalue arg2,
288 		     location loc = location ());
289     rvalue new_call (function func,
290 		     rvalue arg0, rvalue arg1, rvalue arg2,
291 		     rvalue arg3,
292 		     location loc = location ());
293     rvalue new_call (function func,
294 		     rvalue arg0, rvalue arg1, rvalue arg2,
295 		     rvalue arg3, rvalue arg4,
296 		     location loc = location ());
297     rvalue new_call (function func,
298 		     rvalue arg0, rvalue arg1, rvalue arg2,
299 		     rvalue arg3, rvalue arg4, rvalue arg5,
300 		     location loc = location ());
301 
302     rvalue new_cast (rvalue expr,
303 		     type type_,
304 		     location loc = location ());
305 
306     lvalue new_array_access (rvalue ptr,
307 			     rvalue index,
308 			     location loc = location ());
309 
310     case_ new_case (rvalue min_value,
311 		    rvalue max_value,
312 		    block dest_block);
313 
314   private:
315     gcc_jit_context *m_inner_ctxt;
316   };
317 
318   class field : public object
319   {
320   public:
321     field ();
322     field (gcc_jit_field *inner);
323 
324     gcc_jit_field *get_inner_field () const;
325   };
326 
327   class type : public object
328   {
329   public:
330     type ();
331     type (gcc_jit_type *inner);
332 
333     gcc_jit_type *get_inner_type () const;
334 
335     type get_pointer ();
336     type get_const ();
337     type get_volatile ();
338     type get_aligned (size_t alignment_in_bytes);
339     type get_vector (size_t num_units);
340 
341     // Shortcuts for getting values of numeric types:
342     rvalue zero ();
343     rvalue one ();
344  };
345 
346   class struct_ : public type
347   {
348   public:
349     struct_ ();
350     struct_ (gcc_jit_struct *inner);
351 
352     gcc_jit_struct *get_inner_struct () const;
353   };
354 
355   class function : public object
356   {
357   public:
358     function ();
359     function (gcc_jit_function *func);
360 
361     gcc_jit_function *get_inner_function () const;
362 
363     void dump_to_dot (const std::string &path);
364 
365     param get_param (int index) const;
366 
367     block new_block ();
368     block new_block (const std::string &name);
369 
370     lvalue new_local (type type_,
371 		      const std::string &name,
372 		      location loc = location ());
373 
374     rvalue get_address (location loc = location ());
375 
376     /* A series of overloaded operator () with various numbers of arguments
377        for a very terse way of creating a call to this function.  The call
378        is created within the same context as the function itself, which may
379        not be what you want.  */
380     rvalue operator() (location loc = location ());
381     rvalue operator() (rvalue arg0,
382 		       location loc = location ());
383     rvalue operator() (rvalue arg0, rvalue arg1,
384 		       location loc = location ());
385     rvalue operator() (rvalue arg0, rvalue arg1, rvalue arg2,
386 		       location loc = location ());
387   };
388 
389   class block : public object
390   {
391   public:
392     block ();
393     block (gcc_jit_block *inner);
394 
395     gcc_jit_block *get_inner_block () const;
396 
397     function get_function () const;
398 
399     void add_eval (rvalue rvalue,
400 		   location loc = location ());
401 
402     void add_assignment (lvalue lvalue,
403 			 rvalue rvalue,
404 			 location loc = location ());
405 
406     void add_assignment_op (lvalue lvalue,
407 			    enum gcc_jit_binary_op op,
408 			    rvalue rvalue,
409 			    location loc = location ());
410 
411     /* A way to add a function call to the body of a function being
412        defined, with various numbers of args.  */
413     rvalue add_call (function other,
414 		     location loc = location ());
415     rvalue add_call (function other,
416 		     rvalue arg0,
417 		     location loc = location ());
418     rvalue add_call (function other,
419 		     rvalue arg0, rvalue arg1,
420 		     location loc = location ());
421     rvalue add_call (function other,
422 		     rvalue arg0, rvalue arg1, rvalue arg2,
423 		     location loc = location ());
424     rvalue add_call (function other,
425 		     rvalue arg0, rvalue arg1, rvalue arg2, rvalue arg3,
426 		     location loc = location ());
427 
428     void add_comment (const std::string &text,
429 		      location loc = location ());
430 
431     void end_with_conditional (rvalue boolval,
432 			       block on_true,
433 			       block on_false,
434 			       location loc = location ());
435 
436     void end_with_jump (block target,
437 			location loc = location ());
438 
439     void end_with_return (rvalue rvalue,
440 			  location loc = location ());
441     void end_with_return (location loc = location ());
442 
443     void end_with_switch (rvalue expr,
444 			  block default_block,
445 			  std::vector <case_> cases,
446 			  location loc = location ());
447   };
448 
449   class rvalue : public object
450   {
451   public:
452     rvalue ();
453     rvalue (gcc_jit_rvalue *inner);
454     gcc_jit_rvalue *get_inner_rvalue () const;
455 
456     type get_type ();
457 
458     rvalue access_field (field field,
459 			 location loc = location ());
460 
461     lvalue dereference_field (field field,
462 			      location loc = location ());
463 
464     lvalue dereference (location loc = location ());
465 
466     rvalue cast_to (type type_,
467 		    location loc = location ());
468 
469     /* Array access.  */
470     lvalue operator[] (rvalue index);
471     lvalue operator[] (int index);
472   };
473 
474   class lvalue : public rvalue
475   {
476   public:
477     lvalue ();
478     lvalue (gcc_jit_lvalue *inner);
479 
480     gcc_jit_lvalue *get_inner_lvalue () const;
481 
482     lvalue access_field (field field,
483 			 location loc = location ());
484 
485     rvalue get_address (location loc = location ());
486   };
487 
488   class param : public lvalue
489   {
490   public:
491     param ();
492     param (gcc_jit_param *inner);
493 
494     gcc_jit_param *get_inner_param () const;
495   };
496 
497   class case_ : public object
498   {
499   public:
500     case_ ();
501     case_ (gcc_jit_case *inner);
502 
503     gcc_jit_case *get_inner_case () const;
504   };
505 
506   /* Overloaded operators, for those who want the most terse API
507      (at the possible risk of being a little too magical).
508 
509      In each case, the first parameter is used to determine which context
510      owns the resulting expression, and, where appropriate,  what the
511      latter's type is. */
512 
513   /* Unary operators.  */
514   rvalue operator- (rvalue a); // unary minus
515   rvalue operator~ (rvalue a); // unary bitwise negate
516   rvalue operator! (rvalue a); // unary logical negate
517 
518   /* Binary operators.  */
519   rvalue operator+ (rvalue a, rvalue b);
520   rvalue operator- (rvalue a, rvalue b);
521   rvalue operator* (rvalue a, rvalue b);
522   rvalue operator/ (rvalue a, rvalue b);
523   rvalue operator% (rvalue a, rvalue b);
524   rvalue operator& (rvalue a, rvalue b); //  bitwise and
525   rvalue operator^ (rvalue a, rvalue b); // bitwise_xor
526   rvalue operator| (rvalue a, rvalue b); // bitwise_or
527   rvalue operator&& (rvalue a, rvalue b); // logical_and
528   rvalue operator|| (rvalue a, rvalue b); // logical_or
529 
530   /* Comparisons.  */
531   rvalue operator== (rvalue a, rvalue b);
532   rvalue operator!= (rvalue a, rvalue b);
533   rvalue operator< (rvalue a, rvalue b);
534   rvalue operator<= (rvalue a, rvalue b);
535   rvalue operator> (rvalue a, rvalue b);
536   rvalue operator>= (rvalue a, rvalue b);
537 
538   /* Dereferencing. */
539   lvalue operator* (rvalue ptr);
540 
541   class timer
542   {
543   public:
544     timer ();
545     timer (gcc_jit_timer *inner_timer);
546 
547     void push (const char *item_name);
548     void pop (const char *item_name);
549     void print (FILE *f_out) const;
550 
551     void release ();
552 
553     gcc_jit_timer *get_inner_timer () const;
554 
555   private:
556     gcc_jit_timer *m_inner_timer;
557   };
558 
559   class auto_time
560   {
561   public:
562     auto_time (timer t, const char *item_name);
563     auto_time (context ctxt, const char *item_name);
564     ~auto_time ();
565 
566   private:
567     timer m_timer;
568     const char *m_item_name;
569   };
570 }
571 
572 /****************************************************************************
573  Implementation of the API
574  ****************************************************************************/
575 namespace gccjit {
576 
577 // class context
acquire()578 inline context context::acquire ()
579 {
580   return context (gcc_jit_context_acquire ());
581 }
context()582 inline context::context () : m_inner_ctxt (NULL) {}
context(gcc_jit_context * inner)583 inline context::context (gcc_jit_context *inner) : m_inner_ctxt (inner)
584 {
585   if (!inner)
586     throw error ();
587 }
588 
589 inline gccjit::context
new_child_context()590 context::new_child_context ()
591 {
592   return context (gcc_jit_context_new_child_context (m_inner_ctxt));
593 }
594 
595 inline void
release()596 context::release ()
597 {
598   gcc_jit_context_release (m_inner_ctxt);
599   m_inner_ctxt = NULL;
600 }
601 
602 inline gcc_jit_result *
compile()603 context::compile ()
604 {
605   gcc_jit_result *result = gcc_jit_context_compile (m_inner_ctxt);
606   if (!result)
607     throw error ();
608   return result;
609 }
610 
611 inline void
compile_to_file(enum gcc_jit_output_kind output_kind,const char * output_path)612 context::compile_to_file (enum gcc_jit_output_kind output_kind,
613 			  const char *output_path)
614 {
615   gcc_jit_context_compile_to_file (m_inner_ctxt,
616 				   output_kind,
617 				   output_path);
618 }
619 
620 inline void
dump_to_file(const std::string & path,bool update_locations)621 context::dump_to_file (const std::string &path,
622 		       bool update_locations)
623 {
624   gcc_jit_context_dump_to_file (m_inner_ctxt,
625 				path.c_str (),
626 				update_locations);
627 }
628 
629 inline void
set_logfile(FILE * logfile,int flags,int verbosity)630 context::set_logfile (FILE *logfile,
631 		      int flags,
632 		      int verbosity)
633 {
634   gcc_jit_context_set_logfile (m_inner_ctxt,
635 			       logfile,
636 			       flags,
637 			       verbosity);
638 }
639 
640 inline void
dump_reproducer_to_file(const char * path)641 context::dump_reproducer_to_file (const char *path)
642 {
643   gcc_jit_context_dump_reproducer_to_file (m_inner_ctxt,
644 					   path);
645 }
646 
647 inline void
set_str_option(enum gcc_jit_str_option opt,const char * value)648 context::set_str_option (enum gcc_jit_str_option opt,
649 			 const char *value)
650 {
651   gcc_jit_context_set_str_option (m_inner_ctxt, opt, value);
652 
653 }
654 
655 inline void
set_int_option(enum gcc_jit_int_option opt,int value)656 context::set_int_option (enum gcc_jit_int_option opt,
657 			 int value)
658 {
659   gcc_jit_context_set_int_option (m_inner_ctxt, opt, value);
660 
661 }
662 
663 inline void
set_bool_option(enum gcc_jit_bool_option opt,int value)664 context::set_bool_option (enum gcc_jit_bool_option opt,
665 			  int value)
666 {
667   gcc_jit_context_set_bool_option (m_inner_ctxt, opt, value);
668 }
669 
670 inline void
set_bool_allow_unreachable_blocks(int bool_value)671 context::set_bool_allow_unreachable_blocks (int bool_value)
672 {
673   gcc_jit_context_set_bool_allow_unreachable_blocks (m_inner_ctxt,
674 						     bool_value);
675 }
676 
677 inline void
set_bool_use_external_driver(int bool_value)678 context::set_bool_use_external_driver (int bool_value)
679 {
680   gcc_jit_context_set_bool_use_external_driver (m_inner_ctxt,
681 						bool_value);
682 }
683 
684 inline void
add_command_line_option(const char * optname)685 context::add_command_line_option (const char *optname)
686 {
687   gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
688 }
689 
690 inline void
add_driver_option(const char * optname)691 context::add_driver_option (const char *optname)
692 {
693   gcc_jit_context_add_driver_option (m_inner_ctxt, optname);
694 }
695 
696 inline void
set_timer(gccjit::timer t)697 context::set_timer (gccjit::timer t)
698 {
699   gcc_jit_context_set_timer (m_inner_ctxt, t.get_inner_timer ());
700 }
701 
702 inline gccjit::timer
get_timer()703 context::get_timer () const
704 {
705   return gccjit::timer (gcc_jit_context_get_timer (m_inner_ctxt));
706 }
707 
708 
709 inline location
new_location(const std::string & filename,int line,int column)710 context::new_location (const std::string &filename,
711 		       int line,
712 		       int column)
713 {
714   return location (gcc_jit_context_new_location (m_inner_ctxt,
715 						 filename.c_str (),
716 						 line,
717 						 column));
718 }
719 
720 inline type
get_type(enum gcc_jit_types kind)721 context::get_type (enum gcc_jit_types kind)
722 {
723   return type (gcc_jit_context_get_type (m_inner_ctxt, kind));
724 }
725 
726 inline type
get_int_type(size_t num_bytes,int is_signed)727 context::get_int_type (size_t num_bytes, int is_signed)
728 {
729   return type (gcc_jit_context_get_int_type (m_inner_ctxt,
730 					     num_bytes,
731 					     is_signed));
732 }
733 
734 template <typename T>
735 inline type
get_int_type()736 context::get_int_type ()
737 {
738   return get_int_type (sizeof (T), std::numeric_limits<T>::is_signed);
739 }
740 
741 inline type
new_array_type(type element_type,int num_elements,location loc)742 context::new_array_type (type element_type, int num_elements, location loc)
743 {
744   return type (gcc_jit_context_new_array_type (
745 		 m_inner_ctxt,
746 		 loc.get_inner_location (),
747 		 element_type.get_inner_type (),
748 		 num_elements));
749 }
750 
751 inline field
new_field(type type_,const std::string & name,location loc)752 context::new_field (type type_, const std::string &name, location loc)
753 {
754   return field (gcc_jit_context_new_field (m_inner_ctxt,
755 					   loc.get_inner_location (),
756 					   type_.get_inner_type (),
757 					   name.c_str ()));
758 }
759 
760 inline struct_
new_struct_type(const std::string & name,std::vector<field> & fields,location loc)761 context::new_struct_type (const std::string &name,
762 			  std::vector<field> &fields,
763 			  location loc)
764 {
765   /* Treat std::vector as an array, relying on it not being resized: */
766   field *as_array_of_wrappers = &fields[0];
767 
768   /* Treat the array as being of the underlying pointers, relying on
769      the wrapper type being such a pointer internally.	*/
770   gcc_jit_field **as_array_of_ptrs =
771     reinterpret_cast<gcc_jit_field **> (as_array_of_wrappers);
772 
773   return struct_ (gcc_jit_context_new_struct_type (m_inner_ctxt,
774 						   loc.get_inner_location (),
775 						   name.c_str (),
776 						   fields.size (),
777 						   as_array_of_ptrs));
778 }
779 
780 inline struct_
new_opaque_struct_type(const std::string & name,location loc)781 context::new_opaque_struct_type (const std::string &name,
782 				 location loc)
783 {
784   return struct_ (gcc_jit_context_new_opaque_struct (
785 		    m_inner_ctxt,
786 		    loc.get_inner_location (),
787 		    name.c_str ()));
788 }
789 
790 inline param
new_param(type type_,const std::string & name,location loc)791 context::new_param (type type_,
792 		    const std::string &name,
793 		    location loc)
794 {
795   return param (gcc_jit_context_new_param (m_inner_ctxt,
796 					   loc.get_inner_location (),
797 					   type_.get_inner_type (),
798 					   name.c_str ()));
799 }
800 
801 inline function
new_function(enum gcc_jit_function_kind kind,type return_type,const std::string & name,std::vector<param> & params,int is_variadic,location loc)802 context::new_function (enum gcc_jit_function_kind kind,
803 		       type return_type,
804 		       const std::string &name,
805 		       std::vector<param> &params,
806 		       int is_variadic,
807 		       location loc)
808 {
809   /* Treat std::vector as an array, relying on it not being resized: */
810   param *as_array_of_wrappers = &params[0];
811 
812   /* Treat the array as being of the underlying pointers, relying on
813      the wrapper type being such a pointer internally.	*/
814   gcc_jit_param **as_array_of_ptrs =
815     reinterpret_cast<gcc_jit_param **> (as_array_of_wrappers);
816 
817   return function (gcc_jit_context_new_function (m_inner_ctxt,
818 						 loc.get_inner_location (),
819 						 kind,
820 						 return_type.get_inner_type (),
821 						 name.c_str (),
822 						 params.size (),
823 						 as_array_of_ptrs,
824 						 is_variadic));
825 }
826 
827 inline function
get_builtin_function(const std::string & name)828 context::get_builtin_function (const std::string &name)
829 {
830   return function (gcc_jit_context_get_builtin_function (m_inner_ctxt,
831 							 name.c_str ()));
832 }
833 
834 inline lvalue
new_global(enum gcc_jit_global_kind kind,type type_,const std::string & name,location loc)835 context::new_global (enum gcc_jit_global_kind kind,
836 		     type type_,
837 		     const std::string &name,
838 		     location loc)
839 {
840   return lvalue (gcc_jit_context_new_global (m_inner_ctxt,
841 					     loc.get_inner_location (),
842 					     kind,
843 					     type_.get_inner_type (),
844 					     name.c_str ()));
845 }
846 
847 inline rvalue
new_rvalue(type numeric_type,int value)848 context::new_rvalue (type numeric_type,
849 		     int value) const
850 {
851   return rvalue (
852     gcc_jit_context_new_rvalue_from_int (m_inner_ctxt,
853 					 numeric_type.get_inner_type (),
854 					 value));
855 }
856 
857 inline rvalue
new_rvalue(type numeric_type,long value)858 context::new_rvalue (type numeric_type,
859 		     long value) const
860 {
861   return rvalue (
862     gcc_jit_context_new_rvalue_from_long (m_inner_ctxt,
863 					  numeric_type.get_inner_type (),
864 					  value));
865 }
866 
867 inline rvalue
zero(type numeric_type)868 context::zero (type numeric_type) const
869 {
870   return rvalue (gcc_jit_context_zero (m_inner_ctxt,
871 				       numeric_type.get_inner_type ()));
872 }
873 
874 inline rvalue
one(type numeric_type)875 context::one (type numeric_type) const
876 {
877   return rvalue (gcc_jit_context_one (m_inner_ctxt,
878 				       numeric_type.get_inner_type ()));
879 }
880 
881 inline rvalue
new_rvalue(type numeric_type,double value)882 context::new_rvalue (type numeric_type,
883 		     double value) const
884 {
885   return rvalue (
886     gcc_jit_context_new_rvalue_from_double (m_inner_ctxt,
887 					    numeric_type.get_inner_type (),
888 					    value));
889 }
890 
891 inline rvalue
new_rvalue(type pointer_type,void * value)892 context::new_rvalue (type pointer_type,
893 		     void *value) const
894 {
895   return rvalue (
896     gcc_jit_context_new_rvalue_from_ptr (m_inner_ctxt,
897 					 pointer_type.get_inner_type (),
898 					 value));
899 }
900 
901 inline rvalue
new_rvalue(const std::string & value)902 context::new_rvalue (const std::string &value) const
903 {
904   return rvalue (
905     gcc_jit_context_new_string_literal (m_inner_ctxt, value.c_str ()));
906 }
907 
908 inline rvalue
new_rvalue(type vector_type,std::vector<rvalue> elements)909 context::new_rvalue (type vector_type,
910 		     std::vector<rvalue> elements) const
911 {
912   /* Treat std::vector as an array, relying on it not being resized: */
913   rvalue *as_array_of_wrappers = &elements[0];
914 
915   /* Treat the array as being of the underlying pointers, relying on
916      the wrapper type being such a pointer internally.	*/
917   gcc_jit_rvalue **as_array_of_ptrs =
918     reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers);
919 
920   return rvalue (
921     gcc_jit_context_new_rvalue_from_vector (m_inner_ctxt,
922 					    NULL,
923 					    vector_type.get_inner_type (),
924 					    elements.size (),
925 					    as_array_of_ptrs));
926 }
927 
928 inline rvalue
new_unary_op(enum gcc_jit_unary_op op,type result_type,rvalue a,location loc)929 context::new_unary_op (enum gcc_jit_unary_op op,
930 		       type result_type,
931 		       rvalue a,
932 		       location loc)
933 {
934   return rvalue (gcc_jit_context_new_unary_op (m_inner_ctxt,
935 					       loc.get_inner_location (),
936 					       op,
937 					       result_type.get_inner_type (),
938 					       a.get_inner_rvalue ()));
939 }
940 inline rvalue
new_minus(type result_type,rvalue a,location loc)941 context::new_minus (type result_type,
942 		    rvalue a,
943 		    location loc)
944 {
945   return rvalue (new_unary_op (GCC_JIT_UNARY_OP_MINUS,
946 			       result_type, a, loc));
947 }
948 inline rvalue
new_bitwise_negate(type result_type,rvalue a,location loc)949 context::new_bitwise_negate (type result_type,
950 			     rvalue a,
951 			     location loc)
952 {
953   return rvalue (new_unary_op (GCC_JIT_UNARY_OP_BITWISE_NEGATE,
954 			       result_type, a, loc));
955 }
956 inline rvalue
new_logical_negate(type result_type,rvalue a,location loc)957 context::new_logical_negate (type result_type,
958 			     rvalue a,
959 			     location loc)
960 {
961   return rvalue (new_unary_op (GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
962 			       result_type, a, loc));
963 }
964 
965 inline rvalue
new_binary_op(enum gcc_jit_binary_op op,type result_type,rvalue a,rvalue b,location loc)966 context::new_binary_op (enum gcc_jit_binary_op op,
967 			type result_type,
968 			rvalue a, rvalue b,
969 			location loc)
970 {
971   return rvalue (gcc_jit_context_new_binary_op (m_inner_ctxt,
972 						loc.get_inner_location (),
973 						op,
974 						result_type.get_inner_type (),
975 						a.get_inner_rvalue (),
976 						b.get_inner_rvalue ()));
977 }
978 inline rvalue
new_plus(type result_type,rvalue a,rvalue b,location loc)979 context::new_plus (type result_type,
980 		   rvalue a, rvalue b,
981 		   location loc)
982 {
983   return new_binary_op (GCC_JIT_BINARY_OP_PLUS,
984 			result_type, a, b, loc);
985 }
986 inline rvalue
new_minus(type result_type,rvalue a,rvalue b,location loc)987 context::new_minus (type result_type,
988 		    rvalue a, rvalue b,
989 		    location loc)
990 {
991   return new_binary_op (GCC_JIT_BINARY_OP_MINUS,
992 			result_type, a, b, loc);
993 }
994 inline rvalue
new_mult(type result_type,rvalue a,rvalue b,location loc)995 context::new_mult (type result_type,
996 		   rvalue a, rvalue b,
997 		   location loc)
998 {
999   return new_binary_op (GCC_JIT_BINARY_OP_MULT,
1000 			result_type, a, b, loc);
1001 }
1002 inline rvalue
new_divide(type result_type,rvalue a,rvalue b,location loc)1003 context::new_divide (type result_type,
1004 		     rvalue a, rvalue b,
1005 		     location loc)
1006 {
1007   return new_binary_op (GCC_JIT_BINARY_OP_DIVIDE,
1008 			result_type, a, b, loc);
1009 }
1010 inline rvalue
new_modulo(type result_type,rvalue a,rvalue b,location loc)1011 context::new_modulo (type result_type,
1012 		     rvalue a, rvalue b,
1013 		     location loc)
1014 {
1015   return new_binary_op (GCC_JIT_BINARY_OP_MODULO,
1016 			result_type, a, b, loc);
1017 }
1018 inline rvalue
new_bitwise_and(type result_type,rvalue a,rvalue b,location loc)1019 context::new_bitwise_and (type result_type,
1020 			  rvalue a, rvalue b,
1021 			  location loc)
1022 {
1023   return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_AND,
1024 			result_type, a, b, loc);
1025 }
1026 inline rvalue
new_bitwise_xor(type result_type,rvalue a,rvalue b,location loc)1027 context::new_bitwise_xor (type result_type,
1028 			  rvalue a, rvalue b,
1029 			  location loc)
1030 {
1031   return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_XOR,
1032 			result_type, a, b, loc);
1033 }
1034 inline rvalue
new_bitwise_or(type result_type,rvalue a,rvalue b,location loc)1035 context::new_bitwise_or (type result_type,
1036 			 rvalue a, rvalue b,
1037 			 location loc)
1038 {
1039   return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_OR,
1040 			result_type, a, b, loc);
1041 }
1042 inline rvalue
new_logical_and(type result_type,rvalue a,rvalue b,location loc)1043 context::new_logical_and (type result_type,
1044 			  rvalue a, rvalue b,
1045 			  location loc)
1046 {
1047   return new_binary_op (GCC_JIT_BINARY_OP_LOGICAL_AND,
1048 			result_type, a, b, loc);
1049 }
1050 inline rvalue
new_logical_or(type result_type,rvalue a,rvalue b,location loc)1051 context::new_logical_or (type result_type,
1052 			 rvalue a, rvalue b,
1053 			 location loc)
1054 {
1055   return new_binary_op (GCC_JIT_BINARY_OP_LOGICAL_OR,
1056 			result_type, a, b, loc);
1057 }
1058 
1059 inline rvalue
new_comparison(enum gcc_jit_comparison op,rvalue a,rvalue b,location loc)1060 context::new_comparison (enum gcc_jit_comparison op,
1061 			 rvalue a, rvalue b,
1062 			 location loc)
1063 {
1064   return rvalue (gcc_jit_context_new_comparison (m_inner_ctxt,
1065 						 loc.get_inner_location (),
1066 						 op,
1067 						 a.get_inner_rvalue (),
1068 						 b.get_inner_rvalue ()));
1069 }
1070 inline rvalue
new_eq(rvalue a,rvalue b,location loc)1071 context::new_eq (rvalue a, rvalue b,
1072 		 location loc)
1073 {
1074   return new_comparison (GCC_JIT_COMPARISON_EQ,
1075 			 a, b, loc);
1076 }
1077 inline rvalue
new_ne(rvalue a,rvalue b,location loc)1078 context::new_ne (rvalue a, rvalue b,
1079 		 location loc)
1080 {
1081   return new_comparison (GCC_JIT_COMPARISON_NE,
1082 			 a, b, loc);
1083 }
1084 inline rvalue
new_lt(rvalue a,rvalue b,location loc)1085 context::new_lt (rvalue a, rvalue b,
1086 		 location loc)
1087 {
1088   return new_comparison (GCC_JIT_COMPARISON_LT,
1089 			 a, b, loc);
1090 }
1091 inline rvalue
new_le(rvalue a,rvalue b,location loc)1092 context::new_le (rvalue a, rvalue b,
1093 		 location loc)
1094 {
1095   return new_comparison (GCC_JIT_COMPARISON_LE,
1096 			 a, b, loc);
1097 }
1098 inline rvalue
new_gt(rvalue a,rvalue b,location loc)1099 context::new_gt (rvalue a, rvalue b,
1100 		 location loc)
1101 {
1102   return new_comparison (GCC_JIT_COMPARISON_GT,
1103 			 a, b, loc);
1104 }
1105 inline rvalue
new_ge(rvalue a,rvalue b,location loc)1106 context::new_ge (rvalue a, rvalue b,
1107 		 location loc)
1108 {
1109   return new_comparison (GCC_JIT_COMPARISON_GE,
1110 			 a, b, loc);
1111 }
1112 
1113 inline rvalue
new_call(function func,std::vector<rvalue> & args,location loc)1114 context::new_call (function func,
1115 		   std::vector<rvalue> &args,
1116 		   location loc)
1117 {
1118   /* Treat std::vector as an array, relying on it not being resized: */
1119   rvalue *as_array_of_wrappers = &args[0];
1120 
1121   /* Treat the array as being of the underlying pointers, relying on
1122      the wrapper type being such a pointer internally.	*/
1123   gcc_jit_rvalue **as_array_of_ptrs =
1124     reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers);
1125   return gcc_jit_context_new_call (m_inner_ctxt,
1126 				   loc.get_inner_location (),
1127 				   func.get_inner_function (),
1128 				   args.size (),
1129 				   as_array_of_ptrs);
1130 }
1131 inline rvalue
new_call(function func,location loc)1132 context::new_call (function func,
1133 		   location loc)
1134 {
1135   std::vector<rvalue> args;
1136   return new_call (func, args, loc);
1137 }
1138 
1139 inline rvalue
new_call(function func,rvalue arg0,location loc)1140 context::new_call (function func,
1141 		   rvalue arg0,
1142 		   location loc)
1143 {
1144   std::vector<rvalue> args(1);
1145   args[0] = arg0;
1146   return new_call (func, args, loc);
1147 }
1148 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,location loc)1149 context::new_call (function func,
1150 		   rvalue arg0, rvalue arg1,
1151 		   location loc)
1152 {
1153   std::vector<rvalue> args(2);
1154   args[0] = arg0;
1155   args[1] = arg1;
1156   return new_call (func, args, loc);
1157 }
1158 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,location loc)1159 context::new_call (function func,
1160 		   rvalue arg0, rvalue arg1, rvalue arg2,
1161 		   location loc)
1162 {
1163   std::vector<rvalue> args(3);
1164   args[0] = arg0;
1165   args[1] = arg1;
1166   args[2] = arg2;
1167   return new_call (func, args, loc);
1168 }
1169 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,location loc)1170 context::new_call (function func,
1171 		   rvalue arg0, rvalue arg1, rvalue arg2,
1172 		   rvalue arg3,
1173 		   location loc)
1174 {
1175   std::vector<rvalue> args(4);
1176   args[0] = arg0;
1177   args[1] = arg1;
1178   args[2] = arg2;
1179   args[3] = arg3;
1180   return new_call (func, args, loc);
1181 }
1182 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,rvalue arg4,location loc)1183 context::new_call (function func,
1184 		   rvalue arg0, rvalue arg1, rvalue arg2,
1185 		   rvalue arg3, rvalue arg4,
1186 		   location loc)
1187 {
1188   std::vector<rvalue> args(5);
1189   args[0] = arg0;
1190   args[1] = arg1;
1191   args[2] = arg2;
1192   args[3] = arg3;
1193   args[4] = arg4;
1194   return new_call (func, args, loc);
1195 }
1196 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,rvalue arg4,rvalue arg5,location loc)1197 context::new_call (function func,
1198 		   rvalue arg0, rvalue arg1, rvalue arg2,
1199 		   rvalue arg3, rvalue arg4, rvalue arg5,
1200 		   location loc)
1201 {
1202   std::vector<rvalue> args(6);
1203   args[0] = arg0;
1204   args[1] = arg1;
1205   args[2] = arg2;
1206   args[3] = arg3;
1207   args[4] = arg4;
1208   args[5] = arg5;
1209   return new_call (func, args, loc);
1210 }
1211 
1212 inline rvalue
new_cast(rvalue expr,type type_,location loc)1213 context::new_cast (rvalue expr,
1214 		   type type_,
1215 		   location loc)
1216 {
1217   return rvalue (gcc_jit_context_new_cast (m_inner_ctxt,
1218 					   loc.get_inner_location (),
1219 					   expr.get_inner_rvalue (),
1220 					   type_.get_inner_type ()));
1221 }
1222 
1223 inline lvalue
new_array_access(rvalue ptr,rvalue index,location loc)1224 context::new_array_access (rvalue ptr,
1225 			   rvalue index,
1226 			   location loc)
1227 {
1228   return lvalue (gcc_jit_context_new_array_access (m_inner_ctxt,
1229 						   loc.get_inner_location (),
1230 						   ptr.get_inner_rvalue (),
1231 						   index.get_inner_rvalue ()));
1232 }
1233 
1234 inline case_
new_case(rvalue min_value,rvalue max_value,block dest_block)1235 context::new_case (rvalue min_value,
1236 		   rvalue max_value,
1237 		   block dest_block)
1238 {
1239   return case_ (gcc_jit_context_new_case (m_inner_ctxt,
1240 					  min_value.get_inner_rvalue (),
1241 					  max_value.get_inner_rvalue (),
1242 					  dest_block.get_inner_block ()));
1243 }
1244 
1245 // class object
1246 inline context
get_context()1247 object::get_context () const
1248 {
1249   return context (gcc_jit_object_get_context (m_inner_obj));
1250 }
1251 
1252 inline std::string
get_debug_string()1253 object::get_debug_string () const
1254 {
1255   return gcc_jit_object_get_debug_string (m_inner_obj);
1256 }
1257 
object()1258 inline object::object () : m_inner_obj (NULL) {}
object(gcc_jit_object * obj)1259 inline object::object (gcc_jit_object *obj) : m_inner_obj (obj)
1260 {
1261   if (!obj)
1262     throw error ();
1263 }
1264 
1265 inline gcc_jit_object *
get_inner_object()1266 object::get_inner_object () const
1267 {
1268   return m_inner_obj;
1269 }
1270 
1271 inline std::ostream&
1272 operator << (std::ostream& stream, const object &obj)
1273 {
1274   return stream << obj.get_debug_string ();
1275 }
1276 
1277 // class location
location()1278 inline location::location () : object () {}
location(gcc_jit_location * loc)1279 inline location::location (gcc_jit_location *loc)
1280   : object (gcc_jit_location_as_object (loc))
1281 {}
1282 
1283 inline gcc_jit_location *
get_inner_location()1284 location::get_inner_location () const
1285 {
1286   /* Manual downcast: */
1287   return reinterpret_cast<gcc_jit_location *> (get_inner_object ());
1288 }
1289 
1290 // class field
field()1291 inline field::field () : object () {}
field(gcc_jit_field * inner)1292 inline field::field (gcc_jit_field *inner)
1293   : object (gcc_jit_field_as_object (inner))
1294 {}
1295 
1296 inline gcc_jit_field *
get_inner_field()1297 field::get_inner_field () const
1298 {
1299   /* Manual downcast: */
1300   return reinterpret_cast<gcc_jit_field *> (get_inner_object ());
1301 }
1302 
1303 // class type
type()1304 inline type::type () : object () {}
type(gcc_jit_type * inner)1305 inline type::type (gcc_jit_type *inner)
1306   : object (gcc_jit_type_as_object (inner))
1307 {}
1308 
1309 inline gcc_jit_type *
get_inner_type()1310 type::get_inner_type () const
1311 {
1312   /* Manual downcast: */
1313   return reinterpret_cast<gcc_jit_type *> (get_inner_object ());
1314 }
1315 
1316 inline type
get_pointer()1317 type::get_pointer ()
1318 {
1319   return type (gcc_jit_type_get_pointer (get_inner_type ()));
1320 }
1321 
1322 inline type
get_const()1323 type::get_const ()
1324 {
1325   return type (gcc_jit_type_get_const (get_inner_type ()));
1326 }
1327 
1328 inline type
get_volatile()1329 type::get_volatile ()
1330 {
1331   return type (gcc_jit_type_get_volatile (get_inner_type ()));
1332 }
1333 
1334 inline type
get_aligned(size_t alignment_in_bytes)1335 type::get_aligned (size_t alignment_in_bytes)
1336 {
1337   return type (gcc_jit_type_get_aligned (get_inner_type (),
1338 					 alignment_in_bytes));
1339 }
1340 
1341 inline type
get_vector(size_t num_units)1342 type::get_vector (size_t num_units)
1343 {
1344   return type (gcc_jit_type_get_vector (get_inner_type (),
1345 					num_units));
1346 }
1347 
1348 inline rvalue
zero()1349 type::zero ()
1350 {
1351   return get_context ().new_rvalue (*this, 0);
1352 }
1353 
1354 inline rvalue
one()1355 type::one ()
1356 {
1357   return get_context ().new_rvalue (*this, 1);
1358 }
1359 
1360 // class struct_
struct_()1361 inline struct_::struct_ () : type (NULL) {}
struct_(gcc_jit_struct * inner)1362 inline struct_::struct_ (gcc_jit_struct *inner) :
1363   type (gcc_jit_struct_as_type (inner))
1364 {
1365 }
1366 
1367 inline gcc_jit_struct *
get_inner_struct()1368 struct_::get_inner_struct () const
1369 {
1370   /* Manual downcast: */
1371   return reinterpret_cast<gcc_jit_struct *> (get_inner_object ());
1372 }
1373 
1374 // class function
function()1375 inline function::function () : object () {}
function(gcc_jit_function * inner)1376 inline function::function (gcc_jit_function *inner)
1377   : object (gcc_jit_function_as_object (inner))
1378 {}
1379 
1380 inline gcc_jit_function *
get_inner_function()1381 function::get_inner_function () const
1382 {
1383   /* Manual downcast: */
1384   return reinterpret_cast<gcc_jit_function *> (get_inner_object ());
1385 }
1386 
1387 inline void
dump_to_dot(const std::string & path)1388 function::dump_to_dot (const std::string &path)
1389 {
1390   gcc_jit_function_dump_to_dot (get_inner_function (),
1391 				path.c_str ());
1392 }
1393 
1394 inline param
get_param(int index)1395 function::get_param (int index) const
1396 {
1397   return param (gcc_jit_function_get_param (get_inner_function (),
1398 					    index));
1399 }
1400 
1401 inline block
new_block()1402 function::new_block ()
1403 {
1404   return block (gcc_jit_function_new_block (get_inner_function (),
1405 					    NULL));
1406 }
1407 
1408 inline block
new_block(const std::string & name)1409 function::new_block (const std::string &name)
1410 {
1411   return block (gcc_jit_function_new_block (get_inner_function (),
1412 					    name.c_str ()));
1413 }
1414 
1415 inline lvalue
new_local(type type_,const std::string & name,location loc)1416 function::new_local (type type_,
1417 		     const std::string &name,
1418 		     location loc)
1419 {
1420   return lvalue (gcc_jit_function_new_local (get_inner_function (),
1421 					     loc.get_inner_location (),
1422 					     type_.get_inner_type (),
1423 					     name.c_str ()));
1424 }
1425 
1426 inline rvalue
get_address(location loc)1427 function::get_address (location loc)
1428 {
1429   return rvalue (gcc_jit_function_get_address (get_inner_function (),
1430 					       loc.get_inner_location ()));
1431 }
1432 
1433 inline function
get_function()1434 block::get_function () const
1435 {
1436   return function (gcc_jit_block_get_function ( get_inner_block ()));
1437 }
1438 
1439 inline void
add_eval(rvalue rvalue,location loc)1440 block::add_eval (rvalue rvalue,
1441 		 location loc)
1442 {
1443   gcc_jit_block_add_eval (get_inner_block (),
1444 			  loc.get_inner_location (),
1445 			  rvalue.get_inner_rvalue ());
1446 }
1447 
1448 inline void
add_assignment(lvalue lvalue,rvalue rvalue,location loc)1449 block::add_assignment (lvalue lvalue,
1450 		       rvalue rvalue,
1451 		       location loc)
1452 {
1453   gcc_jit_block_add_assignment (get_inner_block (),
1454 				loc.get_inner_location (),
1455 				lvalue.get_inner_lvalue (),
1456 				rvalue.get_inner_rvalue ());
1457 }
1458 
1459 inline void
add_assignment_op(lvalue lvalue,enum gcc_jit_binary_op op,rvalue rvalue,location loc)1460 block::add_assignment_op (lvalue lvalue,
1461 			  enum gcc_jit_binary_op op,
1462 			  rvalue rvalue,
1463 			  location loc)
1464 {
1465   gcc_jit_block_add_assignment_op (get_inner_block (),
1466 				   loc.get_inner_location (),
1467 				   lvalue.get_inner_lvalue (),
1468 				   op,
1469 				   rvalue.get_inner_rvalue ());
1470 }
1471 
1472 inline void
add_comment(const std::string & text,location loc)1473 block::add_comment (const std::string &text,
1474 		    location loc)
1475 {
1476   gcc_jit_block_add_comment (get_inner_block (),
1477 			     loc.get_inner_location (),
1478 			     text.c_str ());
1479 }
1480 
1481 inline void
end_with_conditional(rvalue boolval,block on_true,block on_false,location loc)1482 block::end_with_conditional (rvalue boolval,
1483 			     block on_true,
1484 			     block on_false,
1485 			     location loc)
1486 {
1487   gcc_jit_block_end_with_conditional (get_inner_block (),
1488 				      loc.get_inner_location (),
1489 				      boolval.get_inner_rvalue (),
1490 				      on_true.get_inner_block (),
1491 				      on_false.get_inner_block ());
1492 }
1493 
1494 inline void
end_with_jump(block target,location loc)1495 block::end_with_jump (block target,
1496 		      location loc)
1497 {
1498   gcc_jit_block_end_with_jump (get_inner_block (),
1499 			       loc.get_inner_location (),
1500 			       target.get_inner_block ());
1501 }
1502 
1503 inline void
end_with_return(rvalue rvalue,location loc)1504 block::end_with_return (rvalue rvalue,
1505 			location loc)
1506 {
1507   gcc_jit_block_end_with_return (get_inner_block (),
1508 				 loc.get_inner_location (),
1509 				 rvalue.get_inner_rvalue ());
1510 }
1511 
1512 inline void
end_with_return(location loc)1513 block::end_with_return (location loc)
1514 {
1515   gcc_jit_block_end_with_void_return (get_inner_block (),
1516 				      loc.get_inner_location ());
1517 }
1518 
1519 inline void
end_with_switch(rvalue expr,block default_block,std::vector<case_> cases,location loc)1520 block::end_with_switch (rvalue expr,
1521 			block default_block,
1522 			std::vector <case_> cases,
1523 			location loc)
1524 {
1525   /* Treat std::vector as an array, relying on it not being resized: */
1526   case_ *as_array_of_wrappers = &cases[0];
1527 
1528   /* Treat the array as being of the underlying pointers, relying on
1529      the wrapper type being such a pointer internally.	*/
1530   gcc_jit_case **as_array_of_ptrs =
1531     reinterpret_cast<gcc_jit_case **> (as_array_of_wrappers);
1532   gcc_jit_block_end_with_switch (get_inner_block (),
1533 				 loc.get_inner_location (),
1534 				 expr.get_inner_rvalue (),
1535 				 default_block.get_inner_block (),
1536 				 cases.size (),
1537 				 as_array_of_ptrs);
1538 }
1539 
1540 inline rvalue
add_call(function other,location loc)1541 block::add_call (function other,
1542 		 location loc)
1543 {
1544   rvalue c = get_context ().new_call (other, loc);
1545   add_eval (c);
1546   return c;
1547 }
1548 inline rvalue
add_call(function other,rvalue arg0,location loc)1549 block::add_call (function other,
1550 		 rvalue arg0,
1551 		 location loc)
1552 {
1553   rvalue c = get_context ().new_call (other, arg0, loc);
1554   add_eval (c);
1555   return c;
1556 }
1557 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,location loc)1558 block::add_call (function other,
1559 		 rvalue arg0, rvalue arg1,
1560 		 location loc)
1561 {
1562   rvalue c = get_context ().new_call (other, arg0, arg1, loc);
1563   add_eval (c);
1564   return c;
1565 }
1566 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,rvalue arg2,location loc)1567 block::add_call (function other,
1568 		 rvalue arg0, rvalue arg1, rvalue arg2,
1569 		 location loc)
1570 {
1571   rvalue c = get_context ().new_call (other, arg0, arg1, arg2, loc);
1572   add_eval (c);
1573   return c;
1574 }
1575 
1576 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,location loc)1577 block::add_call (function other,
1578 		 rvalue arg0, rvalue arg1, rvalue arg2, rvalue arg3,
1579 		 location loc)
1580 {
1581   rvalue c = get_context ().new_call (other, arg0, arg1, arg2, arg3, loc);
1582   add_eval (c);
1583   return c;
1584 }
1585 
1586 inline rvalue
operator()1587 function::operator() (location loc)
1588 {
1589   return get_context ().new_call (*this, loc);
1590 }
1591 inline rvalue
operator()1592 function::operator() (rvalue arg0,
1593 		      location loc)
1594 {
1595   return get_context ().new_call (*this,
1596 				  arg0,
1597 				  loc);
1598 }
1599 inline rvalue
operator()1600 function::operator() (rvalue arg0, rvalue arg1,
1601 		      location loc)
1602 {
1603   return get_context ().new_call (*this,
1604 				  arg0, arg1,
1605 				  loc);
1606 }
1607 inline rvalue
operator()1608 function::operator() (rvalue arg0, rvalue arg1, rvalue arg2,
1609 		      location loc)
1610 {
1611   return get_context ().new_call (*this,
1612 				  arg0, arg1, arg2,
1613 				  loc);
1614 }
1615 
1616 // class block
block()1617 inline block::block () : object () {}
block(gcc_jit_block * inner)1618 inline block::block (gcc_jit_block *inner)
1619   : object (gcc_jit_block_as_object (inner))
1620 {}
1621 
1622 inline gcc_jit_block *
get_inner_block()1623 block::get_inner_block () const
1624 {
1625   /* Manual downcast: */
1626   return reinterpret_cast<gcc_jit_block *> (get_inner_object ());
1627 }
1628 
1629 //  class rvalue
rvalue()1630 inline rvalue::rvalue () : object () {}
rvalue(gcc_jit_rvalue * inner)1631 inline rvalue::rvalue (gcc_jit_rvalue *inner)
1632   : object (gcc_jit_rvalue_as_object (inner))
1633 {}
1634 
1635 inline gcc_jit_rvalue *
get_inner_rvalue()1636 rvalue::get_inner_rvalue () const
1637 {
1638   /* Manual downcast: */
1639   return reinterpret_cast<gcc_jit_rvalue *> (get_inner_object ());
1640 }
1641 
1642 inline type
get_type()1643 rvalue::get_type ()
1644 {
1645   return type (gcc_jit_rvalue_get_type (get_inner_rvalue ()));
1646 }
1647 
1648 inline rvalue
access_field(field field,location loc)1649 rvalue::access_field (field field,
1650 		      location loc)
1651 {
1652   return rvalue (gcc_jit_rvalue_access_field (get_inner_rvalue (),
1653 					      loc.get_inner_location (),
1654 					      field.get_inner_field ()));
1655 }
1656 
1657 inline lvalue
dereference_field(field field,location loc)1658 rvalue::dereference_field (field field,
1659 			   location loc)
1660 {
1661   return lvalue (gcc_jit_rvalue_dereference_field (get_inner_rvalue (),
1662 						   loc.get_inner_location (),
1663 						   field.get_inner_field ()));
1664 }
1665 
1666 inline lvalue
dereference(location loc)1667 rvalue::dereference (location loc)
1668 {
1669   return lvalue (gcc_jit_rvalue_dereference (get_inner_rvalue (),
1670 					     loc.get_inner_location ()));
1671 }
1672 
1673 inline rvalue
cast_to(type type_,location loc)1674 rvalue::cast_to (type type_,
1675 		 location loc)
1676 {
1677   return get_context ().new_cast (*this, type_, loc);
1678 }
1679 
1680 inline lvalue
1681 rvalue::operator[] (rvalue index)
1682 {
1683   return get_context ().new_array_access (*this, index);
1684 }
1685 
1686 inline lvalue
1687 rvalue::operator[] (int index)
1688 {
1689   context ctxt = get_context ();
1690   type int_t = ctxt.get_int_type <int> ();
1691   return ctxt.new_array_access (*this,
1692 				ctxt.new_rvalue (int_t,
1693 						 index));
1694 }
1695 
1696 // class lvalue : public rvalue
lvalue()1697 inline lvalue::lvalue () : rvalue () {}
lvalue(gcc_jit_lvalue * inner)1698 inline lvalue::lvalue (gcc_jit_lvalue *inner)
1699   : rvalue (gcc_jit_lvalue_as_rvalue (inner))
1700 {}
1701 
1702 inline gcc_jit_lvalue *
get_inner_lvalue()1703 lvalue::get_inner_lvalue () const
1704 {
1705   /* Manual downcast: */
1706   return reinterpret_cast<gcc_jit_lvalue *> (get_inner_object ());
1707 }
1708 
1709 inline lvalue
access_field(field field,location loc)1710 lvalue::access_field (field field, location loc)
1711 {
1712   return lvalue (gcc_jit_lvalue_access_field (get_inner_lvalue (),
1713 					      loc.get_inner_location (),
1714 					      field.get_inner_field ()));
1715 }
1716 
1717 inline rvalue
get_address(location loc)1718 lvalue::get_address (location loc)
1719 {
1720   return rvalue (gcc_jit_lvalue_get_address (get_inner_lvalue (),
1721 					     loc.get_inner_location ()));
1722 }
1723 
1724 // class param : public lvalue
param()1725 inline param::param () : lvalue () {}
param(gcc_jit_param * inner)1726 inline param::param (gcc_jit_param *inner)
1727   : lvalue (gcc_jit_param_as_lvalue (inner))
1728 {}
1729 
1730 // class case_ : public object
case_()1731 inline case_::case_ () : object () {}
case_(gcc_jit_case * inner)1732 inline case_::case_ (gcc_jit_case *inner)
1733   : object (gcc_jit_case_as_object (inner))
1734 {
1735 }
1736 
1737 inline gcc_jit_case *
get_inner_case()1738 case_::get_inner_case () const
1739 {
1740   /* Manual downcast: */
1741   return reinterpret_cast<gcc_jit_case *> (get_inner_object ());
1742 }
1743 
1744 /* Overloaded operators.  */
1745 // Unary operators
1746 inline rvalue operator- (rvalue a)
1747 {
1748   return a.get_context ().new_minus (a.get_type (), a);
1749 }
1750 inline rvalue operator~ (rvalue a)
1751 {
1752   return a.get_context ().new_bitwise_negate (a.get_type (), a);
1753 }
1754 inline rvalue operator! (rvalue a)
1755 {
1756   return a.get_context ().new_logical_negate (a.get_type (), a);
1757 }
1758 
1759 // Binary operators
1760 inline rvalue operator+ (rvalue a, rvalue b)
1761 {
1762   return a.get_context ().new_plus (a.get_type (), a, b);
1763 }
1764 inline rvalue operator- (rvalue a, rvalue b)
1765 {
1766   return a.get_context ().new_minus (a.get_type (), a, b);
1767 }
1768 inline rvalue operator* (rvalue a, rvalue b)
1769 {
1770   return a.get_context ().new_mult (a.get_type (), a, b);
1771 }
1772 inline rvalue operator/ (rvalue a, rvalue b)
1773 {
1774   return a.get_context ().new_divide (a.get_type (), a, b);
1775 }
1776 inline rvalue operator% (rvalue a, rvalue b)
1777 {
1778   return a.get_context ().new_modulo (a.get_type (), a, b);
1779 }
1780 inline rvalue operator& (rvalue a, rvalue b)
1781 {
1782   return a.get_context ().new_bitwise_and (a.get_type (), a, b);
1783 }
1784 inline rvalue operator^ (rvalue a, rvalue b)
1785 {
1786   return a.get_context ().new_bitwise_xor (a.get_type (), a, b);
1787 }
1788 inline rvalue operator| (rvalue a, rvalue b)
1789 {
1790   return a.get_context ().new_bitwise_or (a.get_type (), a, b);
1791 }
1792 inline rvalue operator&& (rvalue a, rvalue b)
1793 {
1794   return a.get_context ().new_logical_and (a.get_type (), a, b);
1795 }
1796 inline rvalue operator|| (rvalue a, rvalue b)
1797 {
1798   return a.get_context ().new_logical_or (a.get_type (), a, b);
1799 }
1800 
1801 /* Comparisons.  */
1802 inline rvalue operator== (rvalue a, rvalue b)
1803 {
1804   return a.get_context ().new_eq (a, b);
1805 }
1806 inline rvalue operator!= (rvalue a, rvalue b)
1807 {
1808   return a.get_context ().new_ne (a, b);
1809 }
1810 inline rvalue operator< (rvalue a, rvalue b)
1811 {
1812   return a.get_context ().new_lt (a, b);
1813 }
1814 inline rvalue operator<= (rvalue a, rvalue b)
1815 {
1816   return a.get_context ().new_le (a, b);
1817 }
1818 inline rvalue operator> (rvalue a, rvalue b)
1819 {
1820   return a.get_context ().new_gt (a, b);
1821 }
1822 inline rvalue operator>= (rvalue a, rvalue b)
1823 {
1824   return a.get_context ().new_ge (a, b);
1825 }
1826 
1827 /* Dereferencing. */
1828 inline lvalue operator* (rvalue ptr)
1829 {
1830   return ptr.dereference ();
1831 }
1832 
1833 // class timer
1834 inline
timer()1835 timer::timer ()
1836 {
1837   m_inner_timer = gcc_jit_timer_new ();
1838 }
1839 
1840 inline
timer(gcc_jit_timer * inner_timer)1841 timer::timer (gcc_jit_timer *inner_timer)
1842 {
1843   m_inner_timer = inner_timer;
1844 }
1845 
1846 inline void
push(const char * item_name)1847 timer::push (const char *item_name)
1848 {
1849   gcc_jit_timer_push (m_inner_timer, item_name);
1850 
1851 }
1852 
1853 inline void
pop(const char * item_name)1854 timer::pop (const char *item_name)
1855 {
1856   gcc_jit_timer_pop (m_inner_timer, item_name);
1857 }
1858 
1859 inline void
print(FILE * f_out)1860 timer::print (FILE *f_out) const
1861 {
1862   gcc_jit_timer_print (m_inner_timer, f_out);
1863 }
1864 
1865 inline gcc_jit_timer *
get_inner_timer()1866 timer::get_inner_timer () const
1867 {
1868   return m_inner_timer;
1869 }
1870 
1871 inline void
release()1872 timer::release ()
1873 {
1874   gcc_jit_timer_release (m_inner_timer);
1875   m_inner_timer = NULL;
1876 }
1877 
1878 // class auto_time
1879 
1880 inline
auto_time(timer t,const char * item_name)1881 auto_time::auto_time (timer t, const char *item_name)
1882   : m_timer (t),
1883     m_item_name (item_name)
1884 {
1885   t.push (item_name);
1886 }
1887 
1888 inline
auto_time(context ctxt,const char * item_name)1889 auto_time::auto_time (context ctxt, const char *item_name)
1890   : m_timer (ctxt.get_timer ()),
1891     m_item_name (item_name)
1892 {
1893   m_timer.push (item_name);
1894 }
1895 
1896 inline
~auto_time()1897 auto_time::~auto_time ()
1898 {
1899   m_timer.pop (m_item_name);
1900 }
1901 
1902 } // namespace gccjit
1903 
1904 #endif /* #ifndef LIBGCCJIT_PLUS_PLUS_H */
1905