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