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