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