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