1 /* A C++ API for libgccjit, purely as inline wrapper functions.
2 Copyright (C) 2014-2022 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #ifndef LIBGCCJIT_PLUS_PLUS_H
21 #define LIBGCCJIT_PLUS_PLUS_H
22
23 #include "libgccjit.h"
24
25 #include <limits>
26 #include <ostream>
27 #include <vector>
28
29 /****************************************************************************
30 C++ API
31 ****************************************************************************/
32
33 namespace gccjit
34 {
35 /* Indentation indicates inheritance. */
36 class context;
37 class error;
38 class object;
39 class location;
40 class field;
41 class type;
42 class struct_;
43 class function;
44 class block;
45 class rvalue;
46 class lvalue;
47 class param;
48 class case_;
49 class 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
get_inner_context()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> ¶ms,
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 ****************************************************************************/
641 namespace gccjit {
642
643 // class context
acquire()644 inline context context::acquire ()
645 {
646 return context (gcc_jit_context_acquire ());
647 }
context()648 inline context::context () : m_inner_ctxt (NULL) {}
context(gcc_jit_context * inner)649 inline context::context (gcc_jit_context *inner) : m_inner_ctxt (inner)
650 {
651 if (!inner)
652 throw error ();
653 }
654
655 inline gccjit::context
new_child_context()656 context::new_child_context ()
657 {
658 return context (gcc_jit_context_new_child_context (m_inner_ctxt));
659 }
660
661 inline void
release()662 context::release ()
663 {
664 gcc_jit_context_release (m_inner_ctxt);
665 m_inner_ctxt = NULL;
666 }
667
668 inline gcc_jit_result *
compile()669 context::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
677 inline void
compile_to_file(enum gcc_jit_output_kind output_kind,const char * output_path)678 context::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
686 inline void
dump_to_file(const std::string & path,bool update_locations)687 context::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
695 inline void
set_logfile(FILE * logfile,int flags,int verbosity)696 context::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
706 inline void
dump_reproducer_to_file(const char * path)707 context::dump_reproducer_to_file (const char *path)
708 {
709 gcc_jit_context_dump_reproducer_to_file (m_inner_ctxt,
710 path);
711 }
712
713 inline void
set_str_option(enum gcc_jit_str_option opt,const char * value)714 context::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
721 inline void
set_int_option(enum gcc_jit_int_option opt,int value)722 context::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
729 inline void
set_bool_option(enum gcc_jit_bool_option opt,int value)730 context::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
736 inline void
set_bool_allow_unreachable_blocks(int bool_value)737 context::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
743 inline void
set_bool_use_external_driver(int bool_value)744 context::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
750 inline void
add_command_line_option(const char * optname)751 context::add_command_line_option (const char *optname)
752 {
753 gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
754 }
755
756 inline void
add_driver_option(const char * optname)757 context::add_driver_option (const char *optname)
758 {
759 gcc_jit_context_add_driver_option (m_inner_ctxt, optname);
760 }
761
762 inline void
set_timer(gccjit::timer t)763 context::set_timer (gccjit::timer t)
764 {
765 gcc_jit_context_set_timer (m_inner_ctxt, t.get_inner_timer ());
766 }
767
768 inline gccjit::timer
get_timer()769 context::get_timer () const
770 {
771 return gccjit::timer (gcc_jit_context_get_timer (m_inner_ctxt));
772 }
773
774
775 inline location
new_location(const std::string & filename,int line,int column)776 context::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
786 inline type
get_type(enum gcc_jit_types kind)787 context::get_type (enum gcc_jit_types kind)
788 {
789 return type (gcc_jit_context_get_type (m_inner_ctxt, kind));
790 }
791
792 inline type
get_int_type(size_t num_bytes,int is_signed)793 context::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
800 template <typename T>
801 inline type
get_int_type()802 context::get_int_type ()
803 {
804 return get_int_type (sizeof (T), std::numeric_limits<T>::is_signed);
805 }
806
807 inline type
new_array_type(type element_type,int num_elements,location loc)808 context::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
817 inline field
new_field(type type_,const std::string & name,location loc)818 context::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
826 inline field
new_bitfield(type type_,int width,const std::string & name,location loc)827 context::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
837 inline struct_
new_struct_type(const std::string & name,std::vector<field> & fields,location loc)838 context::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
857 inline struct_
new_opaque_struct_type(const std::string & name,location loc)858 context::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
867 inline param
new_param(type type_,const std::string & name,location loc)868 context::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
878 inline function
new_function(enum gcc_jit_function_kind kind,type return_type,const std::string & name,std::vector<param> & params,int is_variadic,location loc)879 context::new_function (enum gcc_jit_function_kind kind,
880 type return_type,
881 const std::string &name,
882 std::vector<param> ¶ms,
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 = ¶ms[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
904 inline function
get_builtin_function(const std::string & name)905 context::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
911 inline lvalue
new_global(enum gcc_jit_global_kind kind,type type_,const std::string & name,location loc)912 context::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
924 inline rvalue
new_rvalue(type numeric_type,int value)925 context::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
934 inline rvalue
new_rvalue(type numeric_type,long value)935 context::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
944 inline rvalue
zero(type numeric_type)945 context::zero (type numeric_type) const
946 {
947 return rvalue (gcc_jit_context_zero (m_inner_ctxt,
948 numeric_type.get_inner_type ()));
949 }
950
951 inline rvalue
one(type numeric_type)952 context::one (type numeric_type) const
953 {
954 return rvalue (gcc_jit_context_one (m_inner_ctxt,
955 numeric_type.get_inner_type ()));
956 }
957
958 inline rvalue
new_rvalue(type numeric_type,double value)959 context::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
968 inline rvalue
new_rvalue(type pointer_type,void * value)969 context::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
978 inline rvalue
new_rvalue(const std::string & value)979 context::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
985 inline rvalue
new_rvalue(type vector_type,std::vector<rvalue> elements)986 context::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
1005 inline rvalue
new_unary_op(enum gcc_jit_unary_op op,type result_type,rvalue a,location loc)1006 context::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 }
1017 inline rvalue
new_minus(type result_type,rvalue a,location loc)1018 context::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 }
1025 inline rvalue
new_bitwise_negate(type result_type,rvalue a,location loc)1026 context::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 }
1033 inline rvalue
new_logical_negate(type result_type,rvalue a,location loc)1034 context::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
1042 inline rvalue
new_binary_op(enum gcc_jit_binary_op op,type result_type,rvalue a,rvalue b,location loc)1043 context::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 }
1055 inline rvalue
new_plus(type result_type,rvalue a,rvalue b,location loc)1056 context::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 }
1063 inline rvalue
new_minus(type result_type,rvalue a,rvalue b,location loc)1064 context::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 }
1071 inline rvalue
new_mult(type result_type,rvalue a,rvalue b,location loc)1072 context::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 }
1079 inline rvalue
new_divide(type result_type,rvalue a,rvalue b,location loc)1080 context::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 }
1087 inline rvalue
new_modulo(type result_type,rvalue a,rvalue b,location loc)1088 context::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 }
1095 inline rvalue
new_bitwise_and(type result_type,rvalue a,rvalue b,location loc)1096 context::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 }
1103 inline rvalue
new_bitwise_xor(type result_type,rvalue a,rvalue b,location loc)1104 context::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 }
1111 inline rvalue
new_bitwise_or(type result_type,rvalue a,rvalue b,location loc)1112 context::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 }
1119 inline rvalue
new_logical_and(type result_type,rvalue a,rvalue b,location loc)1120 context::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 }
1127 inline rvalue
new_logical_or(type result_type,rvalue a,rvalue b,location loc)1128 context::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
1136 inline rvalue
new_comparison(enum gcc_jit_comparison op,rvalue a,rvalue b,location loc)1137 context::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 }
1147 inline rvalue
new_eq(rvalue a,rvalue b,location loc)1148 context::new_eq (rvalue a, rvalue b,
1149 location loc)
1150 {
1151 return new_comparison (GCC_JIT_COMPARISON_EQ,
1152 a, b, loc);
1153 }
1154 inline rvalue
new_ne(rvalue a,rvalue b,location loc)1155 context::new_ne (rvalue a, rvalue b,
1156 location loc)
1157 {
1158 return new_comparison (GCC_JIT_COMPARISON_NE,
1159 a, b, loc);
1160 }
1161 inline rvalue
new_lt(rvalue a,rvalue b,location loc)1162 context::new_lt (rvalue a, rvalue b,
1163 location loc)
1164 {
1165 return new_comparison (GCC_JIT_COMPARISON_LT,
1166 a, b, loc);
1167 }
1168 inline rvalue
new_le(rvalue a,rvalue b,location loc)1169 context::new_le (rvalue a, rvalue b,
1170 location loc)
1171 {
1172 return new_comparison (GCC_JIT_COMPARISON_LE,
1173 a, b, loc);
1174 }
1175 inline rvalue
new_gt(rvalue a,rvalue b,location loc)1176 context::new_gt (rvalue a, rvalue b,
1177 location loc)
1178 {
1179 return new_comparison (GCC_JIT_COMPARISON_GT,
1180 a, b, loc);
1181 }
1182 inline rvalue
new_ge(rvalue a,rvalue b,location loc)1183 context::new_ge (rvalue a, rvalue b,
1184 location loc)
1185 {
1186 return new_comparison (GCC_JIT_COMPARISON_GE,
1187 a, b, loc);
1188 }
1189
1190 inline rvalue
new_call(function func,std::vector<rvalue> & args,location loc)1191 context::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 }
1208 inline rvalue
new_call(function func,location loc)1209 context::new_call (function func,
1210 location loc)
1211 {
1212 std::vector<rvalue> args;
1213 return new_call (func, args, loc);
1214 }
1215
1216 inline rvalue
new_call(function func,rvalue arg0,location loc)1217 context::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 }
1225 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,location loc)1226 context::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 }
1235 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,location loc)1236 context::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 }
1246 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,location loc)1247 context::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 }
1259 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,rvalue arg4,location loc)1260 context::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 }
1273 inline rvalue
new_call(function func,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,rvalue arg4,rvalue arg5,location loc)1274 context::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
1289 inline rvalue
new_cast(rvalue expr,type type_,location loc)1290 context::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
1300 inline lvalue
new_array_access(rvalue ptr,rvalue index,location loc)1301 context::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
1311 inline case_
new_case(rvalue min_value,rvalue max_value,block dest_block)1312 context::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
1322 inline void
add_top_level_asm(const char * asm_stmts,location loc)1323 context::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
1331 inline context
get_context()1332 object::get_context () const
1333 {
1334 return context (gcc_jit_object_get_context (m_inner_obj));
1335 }
1336
1337 inline std::string
get_debug_string()1338 object::get_debug_string () const
1339 {
1340 return gcc_jit_object_get_debug_string (m_inner_obj);
1341 }
1342
object()1343 inline object::object () : m_inner_obj (NULL) {}
object(gcc_jit_object * obj)1344 inline object::object (gcc_jit_object *obj) : m_inner_obj (obj)
1345 {
1346 if (!obj)
1347 throw error ();
1348 }
1349
1350 inline gcc_jit_object *
get_inner_object()1351 object::get_inner_object () const
1352 {
1353 return m_inner_obj;
1354 }
1355
1356 inline std::ostream&
1357 operator << (std::ostream& stream, const object &obj)
1358 {
1359 return stream << obj.get_debug_string ();
1360 }
1361
1362 // class location
location()1363 inline location::location () : object () {}
location(gcc_jit_location * loc)1364 inline location::location (gcc_jit_location *loc)
1365 : object (gcc_jit_location_as_object (loc))
1366 {}
1367
1368 inline gcc_jit_location *
get_inner_location()1369 location::get_inner_location () const
1370 {
1371 /* Manual downcast: */
1372 return reinterpret_cast<gcc_jit_location *> (get_inner_object ());
1373 }
1374
1375 // class field
field()1376 inline field::field () : object () {}
field(gcc_jit_field * inner)1377 inline field::field (gcc_jit_field *inner)
1378 : object (gcc_jit_field_as_object (inner))
1379 {}
1380
1381 inline gcc_jit_field *
get_inner_field()1382 field::get_inner_field () const
1383 {
1384 /* Manual downcast: */
1385 return reinterpret_cast<gcc_jit_field *> (get_inner_object ());
1386 }
1387
1388 // class type
type()1389 inline type::type () : object () {}
type(gcc_jit_type * inner)1390 inline type::type (gcc_jit_type *inner)
1391 : object (gcc_jit_type_as_object (inner))
1392 {}
1393
1394 inline gcc_jit_type *
get_inner_type()1395 type::get_inner_type () const
1396 {
1397 /* Manual downcast: */
1398 return reinterpret_cast<gcc_jit_type *> (get_inner_object ());
1399 }
1400
1401 inline type
get_pointer()1402 type::get_pointer ()
1403 {
1404 return type (gcc_jit_type_get_pointer (get_inner_type ()));
1405 }
1406
1407 inline type
get_const()1408 type::get_const ()
1409 {
1410 return type (gcc_jit_type_get_const (get_inner_type ()));
1411 }
1412
1413 inline type
get_volatile()1414 type::get_volatile ()
1415 {
1416 return type (gcc_jit_type_get_volatile (get_inner_type ()));
1417 }
1418
1419 inline type
get_aligned(size_t alignment_in_bytes)1420 type::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
1426 inline type
get_vector(size_t num_units)1427 type::get_vector (size_t num_units)
1428 {
1429 return type (gcc_jit_type_get_vector (get_inner_type (),
1430 num_units));
1431 }
1432
1433 inline rvalue
zero()1434 type::zero ()
1435 {
1436 return get_context ().new_rvalue (*this, 0);
1437 }
1438
1439 inline rvalue
one()1440 type::one ()
1441 {
1442 return get_context ().new_rvalue (*this, 1);
1443 }
1444
1445 // class struct_
struct_()1446 inline struct_::struct_ () : type (NULL) {}
struct_(gcc_jit_struct * inner)1447 inline struct_::struct_ (gcc_jit_struct *inner) :
1448 type (gcc_jit_struct_as_type (inner))
1449 {
1450 }
1451
1452 inline gcc_jit_struct *
get_inner_struct()1453 struct_::get_inner_struct () const
1454 {
1455 /* Manual downcast: */
1456 return reinterpret_cast<gcc_jit_struct *> (get_inner_object ());
1457 }
1458
1459 // class function
function()1460 inline function::function () : object () {}
function(gcc_jit_function * inner)1461 inline function::function (gcc_jit_function *inner)
1462 : object (gcc_jit_function_as_object (inner))
1463 {}
1464
1465 inline gcc_jit_function *
get_inner_function()1466 function::get_inner_function () const
1467 {
1468 /* Manual downcast: */
1469 return reinterpret_cast<gcc_jit_function *> (get_inner_object ());
1470 }
1471
1472 inline void
dump_to_dot(const std::string & path)1473 function::dump_to_dot (const std::string &path)
1474 {
1475 gcc_jit_function_dump_to_dot (get_inner_function (),
1476 path.c_str ());
1477 }
1478
1479 inline param
get_param(int index)1480 function::get_param (int index) const
1481 {
1482 return param (gcc_jit_function_get_param (get_inner_function (),
1483 index));
1484 }
1485
1486 inline block
new_block()1487 function::new_block ()
1488 {
1489 return block (gcc_jit_function_new_block (get_inner_function (),
1490 NULL));
1491 }
1492
1493 inline block
new_block(const std::string & name)1494 function::new_block (const std::string &name)
1495 {
1496 return block (gcc_jit_function_new_block (get_inner_function (),
1497 name.c_str ()));
1498 }
1499
1500 inline lvalue
new_local(type type_,const std::string & name,location loc)1501 function::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
1511 inline rvalue
get_address(location loc)1512 function::get_address (location loc)
1513 {
1514 return rvalue (gcc_jit_function_get_address (get_inner_function (),
1515 loc.get_inner_location ()));
1516 }
1517
1518 inline function
get_function()1519 block::get_function () const
1520 {
1521 return function (gcc_jit_block_get_function ( get_inner_block ()));
1522 }
1523
1524 inline void
add_eval(rvalue rvalue,location loc)1525 block::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
1533 inline void
add_assignment(lvalue lvalue,rvalue rvalue,location loc)1534 block::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
1544 inline void
add_assignment_op(lvalue lvalue,enum gcc_jit_binary_op op,rvalue rvalue,location loc)1545 block::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
1557 inline void
add_comment(const std::string & text,location loc)1558 block::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
1566 inline void
end_with_conditional(rvalue boolval,block on_true,block on_false,location loc)1567 block::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
1579 inline void
end_with_jump(block target,location loc)1580 block::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
1588 inline void
end_with_return(rvalue rvalue,location loc)1589 block::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
1597 inline void
end_with_return(location loc)1598 block::end_with_return (location loc)
1599 {
1600 gcc_jit_block_end_with_void_return (get_inner_block (),
1601 loc.get_inner_location ());
1602 }
1603
1604 inline void
end_with_switch(rvalue expr,block default_block,std::vector<case_> cases,location loc)1605 block::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
1625 inline extended_asm
add_extended_asm(const std::string & asm_template,location loc)1626 block::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
1634 inline extended_asm
end_with_extended_asm_goto(const std::string & asm_template,std::vector<block> goto_blocks,block * fallthrough_block,location loc)1635 block::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
1656 inline rvalue
add_call(function other,location loc)1657 block::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 }
1664 inline rvalue
add_call(function other,rvalue arg0,location loc)1665 block::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 }
1673 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,location loc)1674 block::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 }
1682 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,rvalue arg2,location loc)1683 block::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
1692 inline rvalue
add_call(function other,rvalue arg0,rvalue arg1,rvalue arg2,rvalue arg3,location loc)1693 block::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
1702 inline rvalue
operator()1703 function::operator() (location loc)
1704 {
1705 return get_context ().new_call (*this, loc);
1706 }
1707 inline rvalue
operator()1708 function::operator() (rvalue arg0,
1709 location loc)
1710 {
1711 return get_context ().new_call (*this,
1712 arg0,
1713 loc);
1714 }
1715 inline rvalue
operator()1716 function::operator() (rvalue arg0, rvalue arg1,
1717 location loc)
1718 {
1719 return get_context ().new_call (*this,
1720 arg0, arg1,
1721 loc);
1722 }
1723 inline rvalue
operator()1724 function::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
block()1733 inline block::block () : object () {}
block(gcc_jit_block * inner)1734 inline block::block (gcc_jit_block *inner)
1735 : object (gcc_jit_block_as_object (inner))
1736 {}
1737
1738 inline gcc_jit_block *
get_inner_block()1739 block::get_inner_block () const
1740 {
1741 /* Manual downcast: */
1742 return reinterpret_cast<gcc_jit_block *> (get_inner_object ());
1743 }
1744
1745 // class rvalue
rvalue()1746 inline rvalue::rvalue () : object () {}
rvalue(gcc_jit_rvalue * inner)1747 inline rvalue::rvalue (gcc_jit_rvalue *inner)
1748 : object (gcc_jit_rvalue_as_object (inner))
1749 {}
1750
1751 inline gcc_jit_rvalue *
get_inner_rvalue()1752 rvalue::get_inner_rvalue () const
1753 {
1754 /* Manual downcast: */
1755 return reinterpret_cast<gcc_jit_rvalue *> (get_inner_object ());
1756 }
1757
1758 inline type
get_type()1759 rvalue::get_type ()
1760 {
1761 return type (gcc_jit_rvalue_get_type (get_inner_rvalue ()));
1762 }
1763
1764 inline rvalue
access_field(field field,location loc)1765 rvalue::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
1773 inline lvalue
dereference_field(field field,location loc)1774 rvalue::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
1782 inline lvalue
dereference(location loc)1783 rvalue::dereference (location loc)
1784 {
1785 return lvalue (gcc_jit_rvalue_dereference (get_inner_rvalue (),
1786 loc.get_inner_location ()));
1787 }
1788
1789 inline rvalue
cast_to(type type_,location loc)1790 rvalue::cast_to (type type_,
1791 location loc)
1792 {
1793 return get_context ().new_cast (*this, type_, loc);
1794 }
1795
1796 inline lvalue
1797 rvalue::operator[] (rvalue index)
1798 {
1799 return get_context ().new_array_access (*this, index);
1800 }
1801
1802 inline lvalue
1803 rvalue::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
lvalue()1813 inline lvalue::lvalue () : rvalue () {}
lvalue(gcc_jit_lvalue * inner)1814 inline lvalue::lvalue (gcc_jit_lvalue *inner)
1815 : rvalue (gcc_jit_lvalue_as_rvalue (inner))
1816 {}
1817
1818 inline gcc_jit_lvalue *
get_inner_lvalue()1819 lvalue::get_inner_lvalue () const
1820 {
1821 /* Manual downcast: */
1822 return reinterpret_cast<gcc_jit_lvalue *> (get_inner_object ());
1823 }
1824
1825 inline lvalue
access_field(field field,location loc)1826 lvalue::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
1833 inline rvalue
get_address(location loc)1834 lvalue::get_address (location loc)
1835 {
1836 return rvalue (gcc_jit_lvalue_get_address (get_inner_lvalue (),
1837 loc.get_inner_location ()));
1838 }
1839
1840 inline lvalue
set_initializer(const void * blob,size_t num_bytes)1841 lvalue::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
1849 inline lvalue
set_initializer_rvalue(rvalue init_value)1850 lvalue::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
1857 inline rvalue
new_struct_ctor(type type_,std::vector<field> & fields,std::vector<rvalue> & values,location loc)1858 context::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
1887 inline rvalue
new_array_ctor(type type_,std::vector<rvalue> & values,location loc)1888 context::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
1908 inline rvalue
new_union_ctor(type type_,field field,rvalue value,location loc)1909 context::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
param()1925 inline param::param () : lvalue () {}
param(gcc_jit_param * inner)1926 inline param::param (gcc_jit_param *inner)
1927 : lvalue (gcc_jit_param_as_lvalue (inner))
1928 {}
1929
1930 // class case_ : public object
case_()1931 inline case_::case_ () : object () {}
case_(gcc_jit_case * inner)1932 inline case_::case_ (gcc_jit_case *inner)
1933 : object (gcc_jit_case_as_object (inner))
1934 {
1935 }
1936
1937 inline gcc_jit_case *
get_inner_case()1938 case_::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
extended_asm()1945 inline extended_asm::extended_asm () : object () {}
extended_asm(gcc_jit_extended_asm * inner)1946 inline extended_asm::extended_asm (gcc_jit_extended_asm *inner)
1947 : object (gcc_jit_extended_asm_as_object (inner))
1948 {
1949 }
1950
1951 inline extended_asm&
set_volatile_flag(bool flag)1952 extended_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
1958 inline extended_asm&
set_inline_flag(bool flag)1959 extended_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
1965 inline extended_asm&
add_output_operand(const std::string & asm_symbolic_name,const std::string & constraint,gccjit::lvalue dest)1966 extended_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
1978 inline extended_asm&
add_output_operand(const std::string & constraint,gccjit::lvalue dest)1979 extended_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
1990 inline extended_asm&
add_input_operand(const std::string & asm_symbolic_name,const std::string & constraint,gccjit::rvalue src)1991 extended_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
2003 inline extended_asm&
add_input_operand(const std::string & constraint,gccjit::rvalue src)2004 extended_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
2015 inline extended_asm&
add_clobber(const std::string & victim)2016 extended_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
2023 inline gcc_jit_extended_asm *
get_inner_extended_asm()2024 extended_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
2032 inline rvalue operator- (rvalue a)
2033 {
2034 return a.get_context ().new_minus (a.get_type (), a);
2035 }
2036 inline rvalue operator~ (rvalue a)
2037 {
2038 return a.get_context ().new_bitwise_negate (a.get_type (), a);
2039 }
2040 inline rvalue operator! (rvalue a)
2041 {
2042 return a.get_context ().new_logical_negate (a.get_type (), a);
2043 }
2044
2045 // Binary operators
2046 inline rvalue operator+ (rvalue a, rvalue b)
2047 {
2048 return a.get_context ().new_plus (a.get_type (), a, b);
2049 }
2050 inline rvalue operator- (rvalue a, rvalue b)
2051 {
2052 return a.get_context ().new_minus (a.get_type (), a, b);
2053 }
2054 inline rvalue operator* (rvalue a, rvalue b)
2055 {
2056 return a.get_context ().new_mult (a.get_type (), a, b);
2057 }
2058 inline rvalue operator/ (rvalue a, rvalue b)
2059 {
2060 return a.get_context ().new_divide (a.get_type (), a, b);
2061 }
2062 inline rvalue operator% (rvalue a, rvalue b)
2063 {
2064 return a.get_context ().new_modulo (a.get_type (), a, b);
2065 }
2066 inline rvalue operator& (rvalue a, rvalue b)
2067 {
2068 return a.get_context ().new_bitwise_and (a.get_type (), a, b);
2069 }
2070 inline rvalue operator^ (rvalue a, rvalue b)
2071 {
2072 return a.get_context ().new_bitwise_xor (a.get_type (), a, b);
2073 }
2074 inline rvalue operator| (rvalue a, rvalue b)
2075 {
2076 return a.get_context ().new_bitwise_or (a.get_type (), a, b);
2077 }
2078 inline rvalue operator&& (rvalue a, rvalue b)
2079 {
2080 return a.get_context ().new_logical_and (a.get_type (), a, b);
2081 }
2082 inline rvalue operator|| (rvalue a, rvalue b)
2083 {
2084 return a.get_context ().new_logical_or (a.get_type (), a, b);
2085 }
2086
2087 /* Comparisons. */
2088 inline rvalue operator== (rvalue a, rvalue b)
2089 {
2090 return a.get_context ().new_eq (a, b);
2091 }
2092 inline rvalue operator!= (rvalue a, rvalue b)
2093 {
2094 return a.get_context ().new_ne (a, b);
2095 }
2096 inline rvalue operator< (rvalue a, rvalue b)
2097 {
2098 return a.get_context ().new_lt (a, b);
2099 }
2100 inline rvalue operator<= (rvalue a, rvalue b)
2101 {
2102 return a.get_context ().new_le (a, b);
2103 }
2104 inline rvalue operator> (rvalue a, rvalue b)
2105 {
2106 return a.get_context ().new_gt (a, b);
2107 }
2108 inline rvalue operator>= (rvalue a, rvalue b)
2109 {
2110 return a.get_context ().new_ge (a, b);
2111 }
2112
2113 /* Dereferencing. */
2114 inline lvalue operator* (rvalue ptr)
2115 {
2116 return ptr.dereference ();
2117 }
2118
2119 // class timer
2120 inline
timer()2121 timer::timer ()
2122 {
2123 m_inner_timer = gcc_jit_timer_new ();
2124 }
2125
2126 inline
timer(gcc_jit_timer * inner_timer)2127 timer::timer (gcc_jit_timer *inner_timer)
2128 {
2129 m_inner_timer = inner_timer;
2130 }
2131
2132 inline void
push(const char * item_name)2133 timer::push (const char *item_name)
2134 {
2135 gcc_jit_timer_push (m_inner_timer, item_name);
2136
2137 }
2138
2139 inline void
pop(const char * item_name)2140 timer::pop (const char *item_name)
2141 {
2142 gcc_jit_timer_pop (m_inner_timer, item_name);
2143 }
2144
2145 inline void
print(FILE * f_out)2146 timer::print (FILE *f_out) const
2147 {
2148 gcc_jit_timer_print (m_inner_timer, f_out);
2149 }
2150
2151 inline gcc_jit_timer *
get_inner_timer()2152 timer::get_inner_timer () const
2153 {
2154 return m_inner_timer;
2155 }
2156
2157 inline void
release()2158 timer::release ()
2159 {
2160 gcc_jit_timer_release (m_inner_timer);
2161 m_inner_timer = NULL;
2162 }
2163
2164 // class auto_time
2165
2166 inline
auto_time(timer t,const char * item_name)2167 auto_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
2174 inline
auto_time(context ctxt,const char * item_name)2175 auto_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
2182 inline
~auto_time()2183 auto_time::~auto_time ()
2184 {
2185 m_timer.pop (m_item_name);
2186 }
2187
2188 namespace version
2189 {
2190 inline int
major_v()2191 major_v ()
2192 {
2193 return gcc_jit_version_major ();
2194 }
2195
2196 inline int
minor_v()2197 minor_v ()
2198 {
2199 return gcc_jit_version_minor ();
2200 }
2201
2202 inline int
patchlevel_v()2203 patchlevel_v ()
2204 {
2205 return gcc_jit_version_patchlevel ();
2206 }
2207 } // namespace version
2208 } // namespace gccjit
2209
2210 #endif /* #ifndef LIBGCCJIT_PLUS_PLUS_H */
2211