1 \input texinfo @c -*-texinfo-*- 2 @c %**start of header 3 @setfilename libgccjit.info 4 @documentencoding UTF-8 5 @ifinfo 6 @*Generated by Sphinx 2.2.2.@* 7 @end ifinfo 8 @settitle libgccjit Documentation 9 @defindex ge 10 @paragraphindent 0 11 @exampleindent 4 12 @finalout 13 @dircategory Miscellaneous 14 @direntry 15 * libgccjit: (libgccjit.info). GCC-based Just In Time compiler library. 16 @end direntry 17 18 @definfoenclose strong,`,' 19 @definfoenclose emph,`,' 20 @c %**end of header 21 22 @copying 23 @quotation 24 libgccjit 12.0.1 (experimental 20220411), Apr 12, 2022 25 26 David Malcolm 27 28 Copyright @copyright{} 2014-2022 Free Software Foundation, Inc. 29 @end quotation 30 31 @end copying 32 33 @titlepage 34 @title libgccjit Documentation 35 @insertcopying 36 @end titlepage 37 @contents 38 39 @c %** start of user preamble 40 41 @c %** end of user preamble 42 43 @ifnottex 44 @node Top 45 @top libgccjit Documentation 46 @insertcopying 47 @end ifnottex 48 49 @c %**start of body 50 @anchor{index doc}@anchor{0} 51 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 52 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 53 @c 54 @c This is free software: you can redistribute it and/or modify it 55 @c under the terms of the GNU General Public License as published by 56 @c the Free Software Foundation, either version 3 of the License, or 57 @c (at your option) any later version. 58 @c 59 @c This program is distributed in the hope that it will be useful, but 60 @c WITHOUT ANY WARRANTY; without even the implied warranty of 61 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 62 @c General Public License for more details. 63 @c 64 @c You should have received a copy of the GNU General Public License 65 @c along with this program. If not, see 66 @c <https://www.gnu.org/licenses/>. 67 68 This document describes libgccjit@footnote{https://gcc.gnu.org/wiki/JIT}, an API 69 for embedding GCC inside programs and libraries. 70 71 There are actually two APIs for the library: 72 73 74 @itemize * 75 76 @item 77 a pure C API: @code{libgccjit.h} 78 79 @item 80 a C++ wrapper API: @code{libgccjit++.h}. This is a collection of thin 81 wrapper classes around the C API, to save typing. 82 @end itemize 83 84 Contents: 85 86 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 87 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 88 @c 89 @c This is free software: you can redistribute it and/or modify it 90 @c under the terms of the GNU General Public License as published by 91 @c the Free Software Foundation, either version 3 of the License, or 92 @c (at your option) any later version. 93 @c 94 @c This program is distributed in the hope that it will be useful, but 95 @c WITHOUT ANY WARRANTY; without even the implied warranty of 96 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 97 @c General Public License for more details. 98 @c 99 @c You should have received a copy of the GNU General Public License 100 @c along with this program. If not, see 101 @c <https://www.gnu.org/licenses/>. 102 103 @menu 104 * Tutorial:: 105 * Topic Reference:: 106 * C++ bindings for libgccjit:: 107 * Internals:: 108 * Indices and tables:: 109 * Index:: 110 111 @detailmenu 112 --- The Detailed Node Listing --- 113 114 Tutorial 115 116 * Tutorial part 1; Hello world: Tutorial part 1 Hello world. 117 * Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function. 118 * Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables. 119 * Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter. 120 * Tutorial part 5; Implementing an Ahead-of-Time compiler: Tutorial part 5 Implementing an Ahead-of-Time compiler. 121 122 Tutorial part 2: Creating a trivial machine code function 123 124 * Error-handling:: 125 * Options:: 126 * Full example:: 127 128 Tutorial part 3: Loops and variables 129 130 * Expressions; lvalues and rvalues: Expressions lvalues and rvalues. 131 * Control flow:: 132 * Visualizing the control flow graph:: 133 * Full example: Full example<2>. 134 135 Tutorial part 4: Adding JIT-compilation to a toy interpreter 136 137 * Our toy interpreter:: 138 * Compiling to machine code:: 139 * Setting things up:: 140 * Populating the function:: 141 * Verifying the control flow graph:: 142 * Compiling the context:: 143 * Single-stepping through the generated code:: 144 * Examining the generated code:: 145 * Putting it all together:: 146 * Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?. 147 148 Behind the curtain: How does our code get optimized? 149 150 * Optimizing away stack manipulation:: 151 * Elimination of tail recursion:: 152 153 Tutorial part 5: Implementing an Ahead-of-Time compiler 154 155 * The brainf language:: 156 * Converting a brainf script to libgccjit IR:: 157 * Compiling a context to a file:: 158 * Other forms of ahead-of-time-compilation:: 159 160 Topic Reference 161 162 * Compilation contexts:: 163 * Objects:: 164 * Types:: 165 * Expressions:: 166 * Creating and using functions:: 167 * Function pointers: Function pointers<2>. 168 * Source Locations:: 169 * Compiling a context:: 170 * ABI and API compatibility:: 171 * Performance:: 172 * Using Assembly Language with libgccjit:: 173 174 Compilation contexts 175 176 * Lifetime-management:: 177 * Thread-safety:: 178 * Error-handling: Error-handling<2>. 179 * Debugging:: 180 * Options: Options<2>. 181 182 Options 183 184 * String Options:: 185 * Boolean options:: 186 * Integer options:: 187 * Additional command-line options:: 188 189 Types 190 191 * Standard types:: 192 * Pointers@comma{} const@comma{} and volatile: Pointers const and volatile. 193 * Vector types:: 194 * Structures and unions:: 195 * Function pointer types:: 196 * Reflection API:: 197 198 Expressions 199 200 * Rvalues:: 201 * Lvalues:: 202 * Working with pointers@comma{} structs and unions: Working with pointers structs and unions. 203 204 Rvalues 205 206 * Simple expressions:: 207 * Constructor expressions:: 208 * Vector expressions:: 209 * Unary Operations:: 210 * Binary Operations:: 211 * Comparisons:: 212 * Function calls:: 213 * Function pointers:: 214 * Type-coercion:: 215 216 Lvalues 217 218 * Global variables:: 219 220 Creating and using functions 221 222 * Params:: 223 * Functions:: 224 * Blocks:: 225 * Statements:: 226 227 Source Locations 228 229 * Faking it:: 230 231 Compiling a context 232 233 * In-memory compilation:: 234 * Ahead-of-time compilation:: 235 236 ABI and API compatibility 237 238 * Programmatically checking version:: 239 * ABI symbol tags:: 240 241 ABI symbol tags 242 243 * LIBGCCJIT_ABI_0:: 244 * LIBGCCJIT_ABI_1:: 245 * LIBGCCJIT_ABI_2:: 246 * LIBGCCJIT_ABI_3:: 247 * LIBGCCJIT_ABI_4:: 248 * LIBGCCJIT_ABI_5:: 249 * LIBGCCJIT_ABI_6:: 250 * LIBGCCJIT_ABI_7:: 251 * LIBGCCJIT_ABI_8:: 252 * LIBGCCJIT_ABI_9:: 253 * LIBGCCJIT_ABI_10:: 254 * LIBGCCJIT_ABI_11:: 255 * LIBGCCJIT_ABI_12:: 256 * LIBGCCJIT_ABI_13:: 257 * LIBGCCJIT_ABI_14:: 258 * LIBGCCJIT_ABI_15:: 259 * LIBGCCJIT_ABI_16:: 260 * LIBGCCJIT_ABI_17:: 261 * LIBGCCJIT_ABI_18:: 262 * LIBGCCJIT_ABI_19:: 263 * LIBGCCJIT_ABI_20:: 264 * LIBGCCJIT_ABI_21:: 265 * LIBGCCJIT_ABI_22:: 266 * LIBGCCJIT_ABI_23:: 267 * LIBGCCJIT_ABI_24:: 268 269 Performance 270 271 * The timing API:: 272 273 Using Assembly Language with libgccjit 274 275 * Adding assembler instructions within a function:: 276 * Adding top-level assembler statements:: 277 278 C++ bindings for libgccjit 279 280 * Tutorial: Tutorial<2>. 281 * Topic Reference: Topic Reference<2>. 282 283 Tutorial 284 285 * Tutorial part 1; Hello world: Tutorial part 1 Hello world<2>. 286 * Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>. 287 * Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>. 288 * Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>. 289 290 Tutorial part 2: Creating a trivial machine code function 291 292 * Options: Options<3>. 293 * Full example: Full example<3>. 294 295 Tutorial part 3: Loops and variables 296 297 * Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>. 298 * Control flow: Control flow<2>. 299 * Visualizing the control flow graph: Visualizing the control flow graph<2>. 300 * Full example: Full example<4>. 301 302 Tutorial part 4: Adding JIT-compilation to a toy interpreter 303 304 * Our toy interpreter: Our toy interpreter<2>. 305 * Compiling to machine code: Compiling to machine code<2>. 306 * Setting things up: Setting things up<2>. 307 * Populating the function: Populating the function<2>. 308 * Verifying the control flow graph: Verifying the control flow graph<2>. 309 * Compiling the context: Compiling the context<2>. 310 * Single-stepping through the generated code: Single-stepping through the generated code<2>. 311 * Examining the generated code: Examining the generated code<2>. 312 * Putting it all together: Putting it all together<2>. 313 * Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>. 314 315 Behind the curtain: How does our code get optimized? 316 317 * Optimizing away stack manipulation: Optimizing away stack manipulation<2>. 318 * Elimination of tail recursion: Elimination of tail recursion<2>. 319 320 Topic Reference 321 322 * Compilation contexts: Compilation contexts<2>. 323 * Objects: Objects<2>. 324 * Types: Types<2>. 325 * Expressions: Expressions<2>. 326 * Creating and using functions: Creating and using functions<2>. 327 * Source Locations: Source Locations<2>. 328 * Compiling a context: Compiling a context<2>. 329 * Using Assembly Language with libgccjit++:: 330 331 Compilation contexts 332 333 * Lifetime-management: Lifetime-management<2>. 334 * Thread-safety: Thread-safety<2>. 335 * Error-handling: Error-handling<3>. 336 * Debugging: Debugging<2>. 337 * Options: Options<4>. 338 339 Options 340 341 * String Options: String Options<2>. 342 * Boolean options: Boolean options<2>. 343 * Integer options: Integer options<2>. 344 * Additional command-line options: Additional command-line options<2>. 345 346 Types 347 348 * Standard types: Standard types<2>. 349 * Pointers@comma{} const@comma{} and volatile: Pointers const and volatile<2>. 350 * Vector types: Vector types<2>. 351 * Structures and unions: Structures and unions<2>. 352 353 Expressions 354 355 * Rvalues: Rvalues<2>. 356 * Lvalues: Lvalues<2>. 357 * Working with pointers@comma{} structs and unions: Working with pointers structs and unions<2>. 358 359 Rvalues 360 361 * Simple expressions: Simple expressions<2>. 362 * Vector expressions: Vector expressions<2>. 363 * Unary Operations: Unary Operations<2>. 364 * Binary Operations: Binary Operations<2>. 365 * Comparisons: Comparisons<2>. 366 * Function calls: Function calls<2>. 367 * Function pointers: Function pointers<3>. 368 * Type-coercion: Type-coercion<2>. 369 370 Lvalues 371 372 * Global variables: Global variables<2>. 373 374 Creating and using functions 375 376 * Params: Params<2>. 377 * Functions: Functions<2>. 378 * Blocks: Blocks<2>. 379 * Statements: Statements<2>. 380 381 Source Locations 382 383 * Faking it: Faking it<2>. 384 385 Compiling a context 386 387 * In-memory compilation: In-memory compilation<2>. 388 * Ahead-of-time compilation: Ahead-of-time compilation<2>. 389 390 Using Assembly Language with libgccjit++ 391 392 * Adding assembler instructions within a function: Adding assembler instructions within a function<2>. 393 * Adding top-level assembler statements: Adding top-level assembler statements<2>. 394 395 Internals 396 397 * Working on the JIT library:: 398 * Running the test suite:: 399 * Environment variables:: 400 * Packaging notes:: 401 * Overview of code structure:: 402 * Design notes:: 403 * Submitting patches:: 404 405 Running the test suite 406 407 * Running under valgrind:: 408 409 @end detailmenu 410 @end menu 411 412 @node Tutorial,Topic Reference,Top,Top 413 @anchor{intro/index doc}@anchor{1}@anchor{intro/index libgccjit}@anchor{2}@anchor{intro/index tutorial}@anchor{3} 414 @chapter Tutorial 415 416 417 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 418 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 419 @c 420 @c This is free software: you can redistribute it and/or modify it 421 @c under the terms of the GNU General Public License as published by 422 @c the Free Software Foundation, either version 3 of the License, or 423 @c (at your option) any later version. 424 @c 425 @c This program is distributed in the hope that it will be useful, but 426 @c WITHOUT ANY WARRANTY; without even the implied warranty of 427 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 428 @c General Public License for more details. 429 @c 430 @c You should have received a copy of the GNU General Public License 431 @c along with this program. If not, see 432 @c <https://www.gnu.org/licenses/>. 433 434 @menu 435 * Tutorial part 1; Hello world: Tutorial part 1 Hello world. 436 * Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function. 437 * Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables. 438 * Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter. 439 * Tutorial part 5; Implementing an Ahead-of-Time compiler: Tutorial part 5 Implementing an Ahead-of-Time compiler. 440 441 @end menu 442 443 @node Tutorial part 1 Hello world,Tutorial part 2 Creating a trivial machine code function,,Tutorial 444 @anchor{intro/tutorial01 doc}@anchor{4}@anchor{intro/tutorial01 tutorial-part-1-hello-world}@anchor{5} 445 @section Tutorial part 1: Hello world 446 447 448 Before we look at the details of the API, lets look at building and 449 running programs that use the library. 450 451 Heres a toy hello world program that uses the library to synthesize 452 a call to @cite{printf} and uses it to write a message to stdout. 453 454 Dont worry about the content of the program for now; well cover 455 the details in later parts of this tutorial. 456 457 @quotation 458 459 @example 460 /* Smoketest example for libgccjit.so 461 Copyright (C) 2014-2022 Free Software Foundation, Inc. 462 463 This file is part of GCC. 464 465 GCC is free software; you can redistribute it and/or modify it 466 under the terms of the GNU General Public License as published by 467 the Free Software Foundation; either version 3, or (at your option) 468 any later version. 469 470 GCC is distributed in the hope that it will be useful, but 471 WITHOUT ANY WARRANTY; without even the implied warranty of 472 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 473 General Public License for more details. 474 475 You should have received a copy of the GNU General Public License 476 along with GCC; see the file COPYING3. If not see 477 <http://www.gnu.org/licenses/>. */ 478 479 #include <libgccjit.h> 480 481 #include <stdlib.h> 482 #include <stdio.h> 483 484 static void 485 create_code (gcc_jit_context *ctxt) 486 @{ 487 /* Let's try to inject the equivalent of: 488 void 489 greet (const char *name) 490 @{ 491 printf ("hello %s\n", name); 492 @} 493 */ 494 gcc_jit_type *void_type = 495 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); 496 gcc_jit_type *const_char_ptr_type = 497 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR); 498 gcc_jit_param *param_name = 499 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name"); 500 gcc_jit_function *func = 501 gcc_jit_context_new_function (ctxt, NULL, 502 GCC_JIT_FUNCTION_EXPORTED, 503 void_type, 504 "greet", 505 1, ¶m_name, 506 0); 507 508 gcc_jit_param *param_format = 509 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format"); 510 gcc_jit_function *printf_func = 511 gcc_jit_context_new_function (ctxt, NULL, 512 GCC_JIT_FUNCTION_IMPORTED, 513 gcc_jit_context_get_type ( 514 ctxt, GCC_JIT_TYPE_INT), 515 "printf", 516 1, ¶m_format, 517 1); 518 gcc_jit_rvalue *args[2]; 519 args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n"); 520 args[1] = gcc_jit_param_as_rvalue (param_name); 521 522 gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 523 524 gcc_jit_block_add_eval ( 525 block, NULL, 526 gcc_jit_context_new_call (ctxt, 527 NULL, 528 printf_func, 529 2, args)); 530 gcc_jit_block_end_with_void_return (block, NULL); 531 @} 532 533 int 534 main (int argc, char **argv) 535 @{ 536 gcc_jit_context *ctxt; 537 gcc_jit_result *result; 538 539 /* Get a "context" object for working with the library. */ 540 ctxt = gcc_jit_context_acquire (); 541 if (!ctxt) 542 @{ 543 fprintf (stderr, "NULL ctxt"); 544 exit (1); 545 @} 546 547 /* Set some options on the context. 548 Let's see the code being generated, in assembler form. */ 549 gcc_jit_context_set_bool_option ( 550 ctxt, 551 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 552 0); 553 554 /* Populate the context. */ 555 create_code (ctxt); 556 557 /* Compile the code. */ 558 result = gcc_jit_context_compile (ctxt); 559 if (!result) 560 @{ 561 fprintf (stderr, "NULL result"); 562 exit (1); 563 @} 564 565 /* Extract the generated code from "result". */ 566 typedef void (*fn_type) (const char *); 567 fn_type greet = 568 (fn_type)gcc_jit_result_get_code (result, "greet"); 569 if (!greet) 570 @{ 571 fprintf (stderr, "NULL greet"); 572 exit (1); 573 @} 574 575 /* Now call the generated function: */ 576 greet ("world"); 577 fflush (stdout); 578 579 gcc_jit_context_release (ctxt); 580 gcc_jit_result_release (result); 581 return 0; 582 @} 583 @end example 584 @end quotation 585 586 Copy the above to @cite{tut01-hello-world.c}. 587 588 Assuming you have the jit library installed, build the test program 589 using: 590 591 @example 592 $ gcc \ 593 tut01-hello-world.c \ 594 -o tut01-hello-world \ 595 -lgccjit 596 @end example 597 598 You should then be able to run the built program: 599 600 @example 601 $ ./tut01-hello-world 602 hello world 603 @end example 604 605 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 606 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 607 @c 608 @c This is free software: you can redistribute it and/or modify it 609 @c under the terms of the GNU General Public License as published by 610 @c the Free Software Foundation, either version 3 of the License, or 611 @c (at your option) any later version. 612 @c 613 @c This program is distributed in the hope that it will be useful, but 614 @c WITHOUT ANY WARRANTY; without even the implied warranty of 615 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 616 @c General Public License for more details. 617 @c 618 @c You should have received a copy of the GNU General Public License 619 @c along with this program. If not, see 620 @c <https://www.gnu.org/licenses/>. 621 622 @node Tutorial part 2 Creating a trivial machine code function,Tutorial part 3 Loops and variables,Tutorial part 1 Hello world,Tutorial 623 @anchor{intro/tutorial02 doc}@anchor{6}@anchor{intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{7} 624 @section Tutorial part 2: Creating a trivial machine code function 625 626 627 Consider this C function: 628 629 @example 630 int square (int i) 631 @{ 632 return i * i; 633 @} 634 @end example 635 636 How can we construct this at run-time using libgccjit? 637 638 First we need to include the relevant header: 639 640 @example 641 #include <libgccjit.h> 642 @end example 643 644 All state associated with compilation is associated with a 645 @ref{8,,gcc_jit_context *}. 646 647 Create one using @ref{9,,gcc_jit_context_acquire()}: 648 649 @example 650 gcc_jit_context *ctxt; 651 ctxt = gcc_jit_context_acquire (); 652 @end example 653 654 The JIT library has a system of types. It is statically-typed: every 655 expression is of a specific type, fixed at compile-time. In our example, 656 all of the expressions are of the C @cite{int} type, so lets obtain this from 657 the context, as a @ref{a,,gcc_jit_type *}, using 658 @ref{b,,gcc_jit_context_get_type()}: 659 660 @example 661 gcc_jit_type *int_type = 662 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 663 @end example 664 665 @ref{a,,gcc_jit_type *} is an example of a contextual object: every 666 entity in the API is associated with a @ref{8,,gcc_jit_context *}. 667 668 Memory management is easy: all such contextual objects are automatically 669 cleaned up for you when the context is released, using 670 @ref{c,,gcc_jit_context_release()}: 671 672 @example 673 gcc_jit_context_release (ctxt); 674 @end example 675 676 so you dont need to manually track and cleanup all objects, just the 677 contexts. 678 679 Although the API is C-based, there is a form of class hierarchy, which 680 looks like this: 681 682 @example 683 +- gcc_jit_object 684 +- gcc_jit_location 685 +- gcc_jit_type 686 +- gcc_jit_struct 687 +- gcc_jit_field 688 +- gcc_jit_function 689 +- gcc_jit_block 690 +- gcc_jit_rvalue 691 +- gcc_jit_lvalue 692 +- gcc_jit_param 693 @end example 694 695 There are casting methods for upcasting from subclasses to parent classes. 696 For example, @ref{d,,gcc_jit_type_as_object()}: 697 698 @example 699 gcc_jit_object *obj = gcc_jit_type_as_object (int_type); 700 @end example 701 702 One thing you can do with a @ref{e,,gcc_jit_object *} is 703 to ask it for a human-readable description, using 704 @ref{f,,gcc_jit_object_get_debug_string()}: 705 706 @example 707 printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj)); 708 @end example 709 710 giving this text on stdout: 711 712 @example 713 obj: int 714 @end example 715 716 This is invaluable when debugging. 717 718 Lets create the function. To do so, we first need to construct 719 its single parameter, specifying its type and giving it a name, 720 using @ref{10,,gcc_jit_context_new_param()}: 721 722 @example 723 gcc_jit_param *param_i = 724 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 725 @end example 726 727 Now we can create the function, using 728 @ref{11,,gcc_jit_context_new_function()}: 729 730 @example 731 gcc_jit_function *func = 732 gcc_jit_context_new_function (ctxt, NULL, 733 GCC_JIT_FUNCTION_EXPORTED, 734 int_type, 735 "square", 736 1, ¶m_i, 737 0); 738 @end example 739 740 To define the code within the function, we must create basic blocks 741 containing statements. 742 743 Every basic block contains a list of statements, eventually terminated 744 by a statement that either returns, or jumps to another basic block. 745 746 Our function has no control-flow, so we just need one basic block: 747 748 @example 749 gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 750 @end example 751 752 Our basic block is relatively simple: it immediately terminates by 753 returning the value of an expression. 754 755 We can build the expression using @ref{12,,gcc_jit_context_new_binary_op()}: 756 757 @example 758 gcc_jit_rvalue *expr = 759 gcc_jit_context_new_binary_op ( 760 ctxt, NULL, 761 GCC_JIT_BINARY_OP_MULT, int_type, 762 gcc_jit_param_as_rvalue (param_i), 763 gcc_jit_param_as_rvalue (param_i)); 764 @end example 765 766 A @ref{13,,gcc_jit_rvalue *} is another example of a 767 @ref{e,,gcc_jit_object *} subclass. We can upcast it using 768 @ref{14,,gcc_jit_rvalue_as_object()} and as before print it with 769 @ref{f,,gcc_jit_object_get_debug_string()}. 770 771 @example 772 printf ("expr: %s\n", 773 gcc_jit_object_get_debug_string ( 774 gcc_jit_rvalue_as_object (expr))); 775 @end example 776 777 giving this output: 778 779 @example 780 expr: i * i 781 @end example 782 783 Creating the expression in itself doesnt do anything; we have to add 784 this expression to a statement within the block. In this case, we use it 785 to build a return statement, which terminates the basic block: 786 787 @example 788 gcc_jit_block_end_with_return (block, NULL, expr); 789 @end example 790 791 OK, weve populated the context. We can now compile it using 792 @ref{15,,gcc_jit_context_compile()}: 793 794 @example 795 gcc_jit_result *result; 796 result = gcc_jit_context_compile (ctxt); 797 @end example 798 799 and get a @ref{16,,gcc_jit_result *}. 800 801 At this point were done with the context; we can release it: 802 803 @example 804 gcc_jit_context_release (ctxt); 805 @end example 806 807 We can now use @ref{17,,gcc_jit_result_get_code()} to look up a specific 808 machine code routine within the result, in this case, the function we 809 created above. 810 811 @example 812 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 813 if (!fn_ptr) 814 @{ 815 fprintf (stderr, "NULL fn_ptr"); 816 goto error; 817 @} 818 @end example 819 820 We can now cast the pointer to an appropriate function pointer type, and 821 then call it: 822 823 @example 824 typedef int (*fn_type) (int); 825 fn_type square = (fn_type)fn_ptr; 826 printf ("result: %d", square (5)); 827 @end example 828 829 @example 830 result: 25 831 @end example 832 833 Once were done with the code, we can release the result: 834 835 @example 836 gcc_jit_result_release (result); 837 @end example 838 839 We cant call @code{square} anymore once weve released @code{result}. 840 841 @menu 842 * Error-handling:: 843 * Options:: 844 * Full example:: 845 846 @end menu 847 848 @node Error-handling,Options,,Tutorial part 2 Creating a trivial machine code function 849 @anchor{intro/tutorial02 error-handling}@anchor{18} 850 @subsection Error-handling 851 852 853 Various kinds of errors are possible when using the API, such as 854 mismatched types in an assignment. You can only compile and get code 855 from a context if no errors occur. 856 857 Errors are printed on stderr; they typically contain the name of the API 858 entrypoint where the error occurred, and pertinent information on the 859 problem: 860 861 @example 862 ./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *) 863 @end example 864 865 The API is designed to cope with errors without crashing, so you can get 866 away with having a single error-handling check in your code: 867 868 @example 869 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 870 if (!fn_ptr) 871 @{ 872 fprintf (stderr, "NULL fn_ptr"); 873 goto error; 874 @} 875 @end example 876 877 For more information, see the @ref{19,,error-handling guide} 878 within the Topic eference. 879 880 @node Options,Full example,Error-handling,Tutorial part 2 Creating a trivial machine code function 881 @anchor{intro/tutorial02 options}@anchor{1a} 882 @subsection Options 883 884 885 To get more information on whats going on, you can set debugging flags 886 on the context using @ref{1b,,gcc_jit_context_set_bool_option()}. 887 888 @c (I'm deliberately not mentioning 889 @c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think 890 @c it's probably more of use to implementors than to users) 891 892 Setting @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE} will dump a 893 C-like representation to stderr when you compile (GCCs GIMPLE 894 representation): 895 896 @example 897 gcc_jit_context_set_bool_option ( 898 ctxt, 899 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 900 1); 901 result = gcc_jit_context_compile (ctxt); 902 @end example 903 904 @example 905 square (signed int i) 906 @{ 907 signed int D.260; 908 909 entry: 910 D.260 = i * i; 911 return D.260; 912 @} 913 @end example 914 915 We can see the generated machine code in assembler form (on stderr) by 916 setting @ref{1d,,GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE} on the context 917 before compiling: 918 919 @example 920 gcc_jit_context_set_bool_option ( 921 ctxt, 922 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 923 1); 924 result = gcc_jit_context_compile (ctxt); 925 @end example 926 927 @example 928 .file "fake.c" 929 .text 930 .globl square 931 .type square, @@function 932 square: 933 .LFB6: 934 .cfi_startproc 935 pushq %rbp 936 .cfi_def_cfa_offset 16 937 .cfi_offset 6, -16 938 movq %rsp, %rbp 939 .cfi_def_cfa_register 6 940 movl %edi, -4(%rbp) 941 .L14: 942 movl -4(%rbp), %eax 943 imull -4(%rbp), %eax 944 popq %rbp 945 .cfi_def_cfa 7, 8 946 ret 947 .cfi_endproc 948 .LFE6: 949 .size square, .-square 950 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 951 .section .note.GNU-stack,"",@@progbits 952 @end example 953 954 By default, no optimizations are performed, the equivalent of GCCs 955 @cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling 956 @ref{1e,,gcc_jit_context_set_int_option()} with 957 @ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 958 959 @example 960 gcc_jit_context_set_int_option ( 961 ctxt, 962 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 963 3); 964 @end example 965 966 @example 967 .file "fake.c" 968 .text 969 .p2align 4,,15 970 .globl square 971 .type square, @@function 972 square: 973 .LFB7: 974 .cfi_startproc 975 .L16: 976 movl %edi, %eax 977 imull %edi, %eax 978 ret 979 .cfi_endproc 980 .LFE7: 981 .size square, .-square 982 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 983 .section .note.GNU-stack,"",@@progbits 984 @end example 985 986 Naturally this has only a small effect on such a trivial function. 987 988 @node Full example,,Options,Tutorial part 2 Creating a trivial machine code function 989 @anchor{intro/tutorial02 full-example}@anchor{20} 990 @subsection Full example 991 992 993 Heres what the above looks like as a complete program: 994 995 @quotation 996 997 @example 998 /* Usage example for libgccjit.so 999 Copyright (C) 2014-2022 Free Software Foundation, Inc. 1000 1001 This file is part of GCC. 1002 1003 GCC is free software; you can redistribute it and/or modify it 1004 under the terms of the GNU General Public License as published by 1005 the Free Software Foundation; either version 3, or (at your option) 1006 any later version. 1007 1008 GCC is distributed in the hope that it will be useful, but 1009 WITHOUT ANY WARRANTY; without even the implied warranty of 1010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1011 General Public License for more details. 1012 1013 You should have received a copy of the GNU General Public License 1014 along with GCC; see the file COPYING3. If not see 1015 <http://www.gnu.org/licenses/>. */ 1016 1017 #include <libgccjit.h> 1018 1019 #include <stdlib.h> 1020 #include <stdio.h> 1021 1022 void 1023 create_code (gcc_jit_context *ctxt) 1024 @{ 1025 /* Let's try to inject the equivalent of: 1026 1027 int square (int i) 1028 @{ 1029 return i * i; 1030 @} 1031 */ 1032 gcc_jit_type *int_type = 1033 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1034 gcc_jit_param *param_i = 1035 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 1036 gcc_jit_function *func = 1037 gcc_jit_context_new_function (ctxt, NULL, 1038 GCC_JIT_FUNCTION_EXPORTED, 1039 int_type, 1040 "square", 1041 1, ¶m_i, 1042 0); 1043 1044 gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 1045 1046 gcc_jit_rvalue *expr = 1047 gcc_jit_context_new_binary_op ( 1048 ctxt, NULL, 1049 GCC_JIT_BINARY_OP_MULT, int_type, 1050 gcc_jit_param_as_rvalue (param_i), 1051 gcc_jit_param_as_rvalue (param_i)); 1052 1053 gcc_jit_block_end_with_return (block, NULL, expr); 1054 @} 1055 1056 int 1057 main (int argc, char **argv) 1058 @{ 1059 gcc_jit_context *ctxt = NULL; 1060 gcc_jit_result *result = NULL; 1061 1062 /* Get a "context" object for working with the library. */ 1063 ctxt = gcc_jit_context_acquire (); 1064 if (!ctxt) 1065 @{ 1066 fprintf (stderr, "NULL ctxt"); 1067 goto error; 1068 @} 1069 1070 /* Set some options on the context. 1071 Let's see the code being generated, in assembler form. */ 1072 gcc_jit_context_set_bool_option ( 1073 ctxt, 1074 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1075 0); 1076 1077 /* Populate the context. */ 1078 create_code (ctxt); 1079 1080 /* Compile the code. */ 1081 result = gcc_jit_context_compile (ctxt); 1082 if (!result) 1083 @{ 1084 fprintf (stderr, "NULL result"); 1085 goto error; 1086 @} 1087 1088 /* We're done with the context; we can release it: */ 1089 gcc_jit_context_release (ctxt); 1090 ctxt = NULL; 1091 1092 /* Extract the generated code from "result". */ 1093 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 1094 if (!fn_ptr) 1095 @{ 1096 fprintf (stderr, "NULL fn_ptr"); 1097 goto error; 1098 @} 1099 1100 typedef int (*fn_type) (int); 1101 fn_type square = (fn_type)fn_ptr; 1102 printf ("result: %d\n", square (5)); 1103 1104 error: 1105 if (ctxt) 1106 gcc_jit_context_release (ctxt); 1107 if (result) 1108 gcc_jit_result_release (result); 1109 return 0; 1110 @} 1111 @end example 1112 @end quotation 1113 1114 Building and running it: 1115 1116 @example 1117 $ gcc \ 1118 tut02-square.c \ 1119 -o tut02-square \ 1120 -lgccjit 1121 1122 # Run the built program: 1123 $ ./tut02-square 1124 result: 25 1125 @end example 1126 1127 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 1128 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 1129 @c 1130 @c This is free software: you can redistribute it and/or modify it 1131 @c under the terms of the GNU General Public License as published by 1132 @c the Free Software Foundation, either version 3 of the License, or 1133 @c (at your option) any later version. 1134 @c 1135 @c This program is distributed in the hope that it will be useful, but 1136 @c WITHOUT ANY WARRANTY; without even the implied warranty of 1137 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1138 @c General Public License for more details. 1139 @c 1140 @c You should have received a copy of the GNU General Public License 1141 @c along with this program. If not, see 1142 @c <https://www.gnu.org/licenses/>. 1143 1144 @node Tutorial part 3 Loops and variables,Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial part 2 Creating a trivial machine code function,Tutorial 1145 @anchor{intro/tutorial03 doc}@anchor{21}@anchor{intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{22} 1146 @section Tutorial part 3: Loops and variables 1147 1148 1149 Consider this C function: 1150 1151 @quotation 1152 1153 @example 1154 int loop_test (int n) 1155 @{ 1156 int sum = 0; 1157 for (int i = 0; i < n; i++) 1158 sum += i * i; 1159 return sum; 1160 @} 1161 @end example 1162 @end quotation 1163 1164 This example demonstrates some more features of libgccjit, with local 1165 variables and a loop. 1166 1167 To break this down into libgccjit terms, its usually easier to reword 1168 the @cite{for} loop as a @cite{while} loop, giving: 1169 1170 @quotation 1171 1172 @example 1173 int loop_test (int n) 1174 @{ 1175 int sum = 0; 1176 int i = 0; 1177 while (i < n) 1178 @{ 1179 sum += i * i; 1180 i++; 1181 @} 1182 return sum; 1183 @} 1184 @end example 1185 @end quotation 1186 1187 Heres what the final control flow graph will look like: 1188 1189 @quotation 1190 1191 1192 @float Figure 1193 1194 @image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png} 1195 1196 @end float 1197 1198 @end quotation 1199 1200 As before, we include the libgccjit header and make a 1201 @ref{8,,gcc_jit_context *}. 1202 1203 @example 1204 #include <libgccjit.h> 1205 1206 void test (void) 1207 @{ 1208 gcc_jit_context *ctxt; 1209 ctxt = gcc_jit_context_acquire (); 1210 @end example 1211 1212 The function works with the C @cite{int} type: 1213 1214 @example 1215 gcc_jit_type *the_type = 1216 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1217 gcc_jit_type *return_type = the_type; 1218 @end example 1219 1220 though we could equally well make it work on, say, @cite{double}: 1221 1222 @example 1223 gcc_jit_type *the_type = 1224 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); 1225 @end example 1226 1227 Lets build the function: 1228 1229 @example 1230 gcc_jit_param *n = 1231 gcc_jit_context_new_param (ctxt, NULL, the_type, "n"); 1232 gcc_jit_param *params[1] = @{n@}; 1233 gcc_jit_function *func = 1234 gcc_jit_context_new_function (ctxt, NULL, 1235 GCC_JIT_FUNCTION_EXPORTED, 1236 return_type, 1237 "loop_test", 1238 1, params, 0); 1239 @end example 1240 1241 @menu 1242 * Expressions; lvalues and rvalues: Expressions lvalues and rvalues. 1243 * Control flow:: 1244 * Visualizing the control flow graph:: 1245 * Full example: Full example<2>. 1246 1247 @end menu 1248 1249 @node Expressions lvalues and rvalues,Control flow,,Tutorial part 3 Loops and variables 1250 @anchor{intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{23} 1251 @subsection Expressions: lvalues and rvalues 1252 1253 1254 The base class of expression is the @ref{13,,gcc_jit_rvalue *}, 1255 representing an expression that can be on the @emph{right}-hand side of 1256 an assignment: a value that can be computed somehow, and assigned 1257 @emph{to} a storage area (such as a variable). It has a specific 1258 @ref{a,,gcc_jit_type *}. 1259 1260 Anothe important class is @ref{24,,gcc_jit_lvalue *}. 1261 A @ref{24,,gcc_jit_lvalue *}. is something that can of the @emph{left}-hand 1262 side of an assignment: a storage area (such as a variable). 1263 1264 In other words, every assignment can be thought of as: 1265 1266 @example 1267 LVALUE = RVALUE; 1268 @end example 1269 1270 Note that @ref{24,,gcc_jit_lvalue *} is a subclass of 1271 @ref{13,,gcc_jit_rvalue *}, where in an assignment of the form: 1272 1273 @example 1274 LVALUE_A = LVALUE_B; 1275 @end example 1276 1277 the @cite{LVALUE_B} implies reading the current value of that storage 1278 area, assigning it into the @cite{LVALUE_A}. 1279 1280 So far the only expressions weve seen are @cite{i * i}: 1281 1282 @example 1283 gcc_jit_rvalue *expr = 1284 gcc_jit_context_new_binary_op ( 1285 ctxt, NULL, 1286 GCC_JIT_BINARY_OP_MULT, int_type, 1287 gcc_jit_param_as_rvalue (param_i), 1288 gcc_jit_param_as_rvalue (param_i)); 1289 @end example 1290 1291 which is a @ref{13,,gcc_jit_rvalue *}, and the various function 1292 parameters: @cite{param_i} and @cite{param_n}, instances of 1293 @ref{25,,gcc_jit_param *}, which is a subclass of 1294 @ref{24,,gcc_jit_lvalue *} (and, in turn, of @ref{13,,gcc_jit_rvalue *}): 1295 we can both read from and write to function parameters within the 1296 body of a function. 1297 1298 Our new example has a couple of local variables. We create them by 1299 calling @ref{26,,gcc_jit_function_new_local()}, supplying a type and a 1300 name: 1301 1302 @example 1303 /* Build locals: */ 1304 gcc_jit_lvalue *i = 1305 gcc_jit_function_new_local (func, NULL, the_type, "i"); 1306 gcc_jit_lvalue *sum = 1307 gcc_jit_function_new_local (func, NULL, the_type, "sum"); 1308 @end example 1309 1310 These are instances of @ref{24,,gcc_jit_lvalue *} - they can be read from 1311 and written to. 1312 1313 Note that there is no precanned way to create @emph{and} initialize a variable 1314 like in C: 1315 1316 @example 1317 int i = 0; 1318 @end example 1319 1320 Instead, having added the local to the function, we have to separately add 1321 an assignment of @cite{0} to @cite{local_i} at the beginning of the function. 1322 1323 @node Control flow,Visualizing the control flow graph,Expressions lvalues and rvalues,Tutorial part 3 Loops and variables 1324 @anchor{intro/tutorial03 control-flow}@anchor{27} 1325 @subsection Control flow 1326 1327 1328 This function has a loop, so we need to build some basic blocks to 1329 handle the control flow. In this case, we need 4 blocks: 1330 1331 1332 @enumerate 1333 1334 @item 1335 before the loop (initializing the locals) 1336 1337 @item 1338 the conditional at the top of the loop (comparing @cite{i < n}) 1339 1340 @item 1341 the body of the loop 1342 1343 @item 1344 after the loop terminates (@cite{return sum}) 1345 @end enumerate 1346 1347 so we create these as @ref{28,,gcc_jit_block *} instances within the 1348 @ref{29,,gcc_jit_function *}: 1349 1350 @example 1351 gcc_jit_block *b_initial = 1352 gcc_jit_function_new_block (func, "initial"); 1353 gcc_jit_block *b_loop_cond = 1354 gcc_jit_function_new_block (func, "loop_cond"); 1355 gcc_jit_block *b_loop_body = 1356 gcc_jit_function_new_block (func, "loop_body"); 1357 gcc_jit_block *b_after_loop = 1358 gcc_jit_function_new_block (func, "after_loop"); 1359 @end example 1360 1361 We now populate each block with statements. 1362 1363 The entry block @cite{b_initial} consists of initializations followed by a jump 1364 to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using 1365 @ref{2a,,gcc_jit_block_add_assignment()} to add 1366 an assignment statement, and using @ref{2b,,gcc_jit_context_zero()} to get 1367 the constant value @cite{0} for the relevant type for the right-hand side of 1368 the assignment: 1369 1370 @example 1371 /* sum = 0; */ 1372 gcc_jit_block_add_assignment ( 1373 b_initial, NULL, 1374 sum, 1375 gcc_jit_context_zero (ctxt, the_type)); 1376 1377 /* i = 0; */ 1378 gcc_jit_block_add_assignment ( 1379 b_initial, NULL, 1380 i, 1381 gcc_jit_context_zero (ctxt, the_type)); 1382 @end example 1383 1384 We can then terminate the entry block by jumping to the conditional: 1385 1386 @example 1387 gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond); 1388 @end example 1389 1390 The conditional block is equivalent to the line @cite{while (i < n)} from our 1391 C example. It contains a single statement: a conditional, which jumps to 1392 one of two destination blocks depending on a boolean 1393 @ref{13,,gcc_jit_rvalue *}, in this case the comparison of @cite{i} and @cite{n}. 1394 We build the comparison using @ref{2c,,gcc_jit_context_new_comparison()}: 1395 1396 @example 1397 /* (i >= n) */ 1398 gcc_jit_rvalue *guard = 1399 gcc_jit_context_new_comparison ( 1400 ctxt, NULL, 1401 GCC_JIT_COMPARISON_GE, 1402 gcc_jit_lvalue_as_rvalue (i), 1403 gcc_jit_param_as_rvalue (n)); 1404 @end example 1405 1406 and can then use this to add @cite{b_loop_cond}s sole statement, via 1407 @ref{2d,,gcc_jit_block_end_with_conditional()}: 1408 1409 @example 1410 /* Equivalent to: 1411 if (guard) 1412 goto after_loop; 1413 else 1414 goto loop_body; */ 1415 gcc_jit_block_end_with_conditional ( 1416 b_loop_cond, NULL, 1417 guard, 1418 b_after_loop, /* on_true */ 1419 b_loop_body); /* on_false */ 1420 @end example 1421 1422 Next, we populate the body of the loop. 1423 1424 The C statement @cite{sum += i * i;} is an assignment operation, where an 1425 lvalue is modified in-place. We use 1426 @ref{2e,,gcc_jit_block_add_assignment_op()} to handle these operations: 1427 1428 @example 1429 /* sum += i * i */ 1430 gcc_jit_block_add_assignment_op ( 1431 b_loop_body, NULL, 1432 sum, 1433 GCC_JIT_BINARY_OP_PLUS, 1434 gcc_jit_context_new_binary_op ( 1435 ctxt, NULL, 1436 GCC_JIT_BINARY_OP_MULT, the_type, 1437 gcc_jit_lvalue_as_rvalue (i), 1438 gcc_jit_lvalue_as_rvalue (i))); 1439 @end example 1440 1441 The @cite{i++} can be thought of as @cite{i += 1}, and can thus be handled in 1442 a similar way. We use @ref{2f,,gcc_jit_context_one()} to get the constant 1443 value @cite{1} (for the relevant type) for the right-hand side 1444 of the assignment. 1445 1446 @example 1447 /* i++ */ 1448 gcc_jit_block_add_assignment_op ( 1449 b_loop_body, NULL, 1450 i, 1451 GCC_JIT_BINARY_OP_PLUS, 1452 gcc_jit_context_one (ctxt, the_type)); 1453 @end example 1454 1455 @cartouche 1456 @quotation Note 1457 For numeric constants other than 0 or 1, we could use 1458 @ref{30,,gcc_jit_context_new_rvalue_from_int()} and 1459 @ref{31,,gcc_jit_context_new_rvalue_from_double()}. 1460 @end quotation 1461 @end cartouche 1462 1463 The loop body completes by jumping back to the conditional: 1464 1465 @example 1466 gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond); 1467 @end example 1468 1469 Finally, we populate the @cite{b_after_loop} block, reached when the loop 1470 conditional is false. We want to generate the equivalent of: 1471 1472 @example 1473 return sum; 1474 @end example 1475 1476 so the block is just one statement: 1477 1478 @example 1479 /* return sum */ 1480 gcc_jit_block_end_with_return ( 1481 b_after_loop, 1482 NULL, 1483 gcc_jit_lvalue_as_rvalue (sum)); 1484 @end example 1485 1486 @cartouche 1487 @quotation Note 1488 You can intermingle block creation with statement creation, 1489 but given that the terminator statements generally include references 1490 to other blocks, I find its clearer to create all the blocks, 1491 @emph{then} all the statements. 1492 @end quotation 1493 @end cartouche 1494 1495 Weve finished populating the function. As before, we can now compile it 1496 to machine code: 1497 1498 @example 1499 gcc_jit_result *result; 1500 result = gcc_jit_context_compile (ctxt); 1501 1502 typedef int (*loop_test_fn_type) (int); 1503 loop_test_fn_type loop_test = 1504 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 1505 if (!loop_test) 1506 goto error; 1507 printf ("result: %d", loop_test (10)); 1508 @end example 1509 1510 @example 1511 result: 285 1512 @end example 1513 1514 @node Visualizing the control flow graph,Full example<2>,Control flow,Tutorial part 3 Loops and variables 1515 @anchor{intro/tutorial03 visualizing-the-control-flow-graph}@anchor{32} 1516 @subsection Visualizing the control flow graph 1517 1518 1519 You can see the control flow graph of a function using 1520 @ref{33,,gcc_jit_function_dump_to_dot()}: 1521 1522 @example 1523 gcc_jit_function_dump_to_dot (func, "/tmp/sum-of-squares.dot"); 1524 @end example 1525 1526 giving a .dot file in GraphViz format. 1527 1528 You can convert this to an image using @cite{dot}: 1529 1530 @example 1531 $ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png 1532 @end example 1533 1534 or use a viewer (my preferred one is xdot.py; see 1535 @indicateurl{https://github.com/jrfonseca/xdot.py}; on Fedora you can 1536 install it with @cite{yum install python-xdot}): 1537 1538 @quotation 1539 1540 1541 @float Figure 1542 1543 @image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png} 1544 1545 @end float 1546 1547 @end quotation 1548 1549 @node Full example<2>,,Visualizing the control flow graph,Tutorial part 3 Loops and variables 1550 @anchor{intro/tutorial03 full-example}@anchor{34} 1551 @subsection Full example 1552 1553 1554 @quotation 1555 1556 @example 1557 /* Usage example for libgccjit.so 1558 Copyright (C) 2014-2022 Free Software Foundation, Inc. 1559 1560 This file is part of GCC. 1561 1562 GCC is free software; you can redistribute it and/or modify it 1563 under the terms of the GNU General Public License as published by 1564 the Free Software Foundation; either version 3, or (at your option) 1565 any later version. 1566 1567 GCC is distributed in the hope that it will be useful, but 1568 WITHOUT ANY WARRANTY; without even the implied warranty of 1569 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1570 General Public License for more details. 1571 1572 You should have received a copy of the GNU General Public License 1573 along with GCC; see the file COPYING3. If not see 1574 <http://www.gnu.org/licenses/>. */ 1575 1576 #include <libgccjit.h> 1577 1578 #include <stdlib.h> 1579 #include <stdio.h> 1580 1581 void 1582 create_code (gcc_jit_context *ctxt) 1583 @{ 1584 /* 1585 Simple sum-of-squares, to test conditionals and looping 1586 1587 int loop_test (int n) 1588 @{ 1589 int i; 1590 int sum = 0; 1591 for (i = 0; i < n ; i ++) 1592 @{ 1593 sum += i * i; 1594 @} 1595 return sum; 1596 */ 1597 gcc_jit_type *the_type = 1598 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1599 gcc_jit_type *return_type = the_type; 1600 1601 gcc_jit_param *n = 1602 gcc_jit_context_new_param (ctxt, NULL, the_type, "n"); 1603 gcc_jit_param *params[1] = @{n@}; 1604 gcc_jit_function *func = 1605 gcc_jit_context_new_function (ctxt, NULL, 1606 GCC_JIT_FUNCTION_EXPORTED, 1607 return_type, 1608 "loop_test", 1609 1, params, 0); 1610 1611 /* Build locals: */ 1612 gcc_jit_lvalue *i = 1613 gcc_jit_function_new_local (func, NULL, the_type, "i"); 1614 gcc_jit_lvalue *sum = 1615 gcc_jit_function_new_local (func, NULL, the_type, "sum"); 1616 1617 gcc_jit_block *b_initial = 1618 gcc_jit_function_new_block (func, "initial"); 1619 gcc_jit_block *b_loop_cond = 1620 gcc_jit_function_new_block (func, "loop_cond"); 1621 gcc_jit_block *b_loop_body = 1622 gcc_jit_function_new_block (func, "loop_body"); 1623 gcc_jit_block *b_after_loop = 1624 gcc_jit_function_new_block (func, "after_loop"); 1625 1626 /* sum = 0; */ 1627 gcc_jit_block_add_assignment ( 1628 b_initial, NULL, 1629 sum, 1630 gcc_jit_context_zero (ctxt, the_type)); 1631 1632 /* i = 0; */ 1633 gcc_jit_block_add_assignment ( 1634 b_initial, NULL, 1635 i, 1636 gcc_jit_context_zero (ctxt, the_type)); 1637 1638 gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond); 1639 1640 /* if (i >= n) */ 1641 gcc_jit_block_end_with_conditional ( 1642 b_loop_cond, NULL, 1643 gcc_jit_context_new_comparison ( 1644 ctxt, NULL, 1645 GCC_JIT_COMPARISON_GE, 1646 gcc_jit_lvalue_as_rvalue (i), 1647 gcc_jit_param_as_rvalue (n)), 1648 b_after_loop, 1649 b_loop_body); 1650 1651 /* sum += i * i */ 1652 gcc_jit_block_add_assignment_op ( 1653 b_loop_body, NULL, 1654 sum, 1655 GCC_JIT_BINARY_OP_PLUS, 1656 gcc_jit_context_new_binary_op ( 1657 ctxt, NULL, 1658 GCC_JIT_BINARY_OP_MULT, the_type, 1659 gcc_jit_lvalue_as_rvalue (i), 1660 gcc_jit_lvalue_as_rvalue (i))); 1661 1662 /* i++ */ 1663 gcc_jit_block_add_assignment_op ( 1664 b_loop_body, NULL, 1665 i, 1666 GCC_JIT_BINARY_OP_PLUS, 1667 gcc_jit_context_one (ctxt, the_type)); 1668 1669 gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond); 1670 1671 /* return sum */ 1672 gcc_jit_block_end_with_return ( 1673 b_after_loop, 1674 NULL, 1675 gcc_jit_lvalue_as_rvalue (sum)); 1676 @} 1677 1678 int 1679 main (int argc, char **argv) 1680 @{ 1681 gcc_jit_context *ctxt = NULL; 1682 gcc_jit_result *result = NULL; 1683 1684 /* Get a "context" object for working with the library. */ 1685 ctxt = gcc_jit_context_acquire (); 1686 if (!ctxt) 1687 @{ 1688 fprintf (stderr, "NULL ctxt"); 1689 goto error; 1690 @} 1691 1692 /* Set some options on the context. 1693 Let's see the code being generated, in assembler form. */ 1694 gcc_jit_context_set_bool_option ( 1695 ctxt, 1696 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1697 0); 1698 1699 /* Populate the context. */ 1700 create_code (ctxt); 1701 1702 /* Compile the code. */ 1703 result = gcc_jit_context_compile (ctxt); 1704 if (!result) 1705 @{ 1706 fprintf (stderr, "NULL result"); 1707 goto error; 1708 @} 1709 1710 /* Extract the generated code from "result". */ 1711 typedef int (*loop_test_fn_type) (int); 1712 loop_test_fn_type loop_test = 1713 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 1714 if (!loop_test) 1715 @{ 1716 fprintf (stderr, "NULL loop_test"); 1717 goto error; 1718 @} 1719 1720 /* Run the generated code. */ 1721 int val = loop_test (10); 1722 printf("loop_test returned: %d\n", val); 1723 1724 error: 1725 gcc_jit_context_release (ctxt); 1726 gcc_jit_result_release (result); 1727 return 0; 1728 @} 1729 @end example 1730 @end quotation 1731 1732 Building and running it: 1733 1734 @example 1735 $ gcc \ 1736 tut03-sum-of-squares.c \ 1737 -o tut03-sum-of-squares \ 1738 -lgccjit 1739 1740 # Run the built program: 1741 $ ./tut03-sum-of-squares 1742 loop_test returned: 285 1743 @end example 1744 1745 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 1746 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 1747 @c 1748 @c This is free software: you can redistribute it and/or modify it 1749 @c under the terms of the GNU General Public License as published by 1750 @c the Free Software Foundation, either version 3 of the License, or 1751 @c (at your option) any later version. 1752 @c 1753 @c This program is distributed in the hope that it will be useful, but 1754 @c WITHOUT ANY WARRANTY; without even the implied warranty of 1755 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1756 @c General Public License for more details. 1757 @c 1758 @c You should have received a copy of the GNU General Public License 1759 @c along with this program. If not, see 1760 @c <https://www.gnu.org/licenses/>. 1761 1762 @node Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial part 5 Implementing an Ahead-of-Time compiler,Tutorial part 3 Loops and variables,Tutorial 1763 @anchor{intro/tutorial04 doc}@anchor{35}@anchor{intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{36} 1764 @section Tutorial part 4: Adding JIT-compilation to a toy interpreter 1765 1766 1767 In this example we construct a toy interpreter, and add JIT-compilation 1768 to it. 1769 1770 @menu 1771 * Our toy interpreter:: 1772 * Compiling to machine code:: 1773 * Setting things up:: 1774 * Populating the function:: 1775 * Verifying the control flow graph:: 1776 * Compiling the context:: 1777 * Single-stepping through the generated code:: 1778 * Examining the generated code:: 1779 * Putting it all together:: 1780 * Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?. 1781 1782 @end menu 1783 1784 @node Our toy interpreter,Compiling to machine code,,Tutorial part 4 Adding JIT-compilation to a toy interpreter 1785 @anchor{intro/tutorial04 our-toy-interpreter}@anchor{37} 1786 @subsection Our toy interpreter 1787 1788 1789 Its a stack-based interpreter, and is intended as a (very simple) example 1790 of the kind of bytecode interpreter seen in dynamic languages such as 1791 Python, Ruby etc. 1792 1793 For the sake of simplicity, our toy virtual machine is very limited: 1794 1795 @quotation 1796 1797 1798 @itemize * 1799 1800 @item 1801 The only data type is @cite{int} 1802 1803 @item 1804 It can only work on one function at a time (so that the only 1805 function call that can be made is to recurse). 1806 1807 @item 1808 Functions can only take one parameter. 1809 1810 @item 1811 Functions have a stack of @cite{int} values. 1812 1813 @item 1814 Well implement function call within the interpreter by calling a 1815 function in our implementation, rather than implementing our own 1816 frame stack. 1817 1818 @item 1819 The parser is only good enough to get the examples to work. 1820 @end itemize 1821 @end quotation 1822 1823 Naturally, a real interpreter would be much more complicated that this. 1824 1825 The following operations are supported: 1826 1827 1828 @multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxx} 1829 @headitem 1830 1831 Operation 1832 1833 @tab 1834 1835 Meaning 1836 1837 @tab 1838 1839 Old Stack 1840 1841 @tab 1842 1843 New Stack 1844 1845 @item 1846 1847 DUP 1848 1849 @tab 1850 1851 Duplicate top of stack. 1852 1853 @tab 1854 1855 @code{[..., x]} 1856 1857 @tab 1858 1859 @code{[..., x, x]} 1860 1861 @item 1862 1863 ROT 1864 1865 @tab 1866 1867 Swap top two elements 1868 of stack. 1869 1870 @tab 1871 1872 @code{[..., x, y]} 1873 1874 @tab 1875 1876 @code{[..., y, x]} 1877 1878 @item 1879 1880 BINARY_ADD 1881 1882 @tab 1883 1884 Add the top two elements 1885 on the stack. 1886 1887 @tab 1888 1889 @code{[..., x, y]} 1890 1891 @tab 1892 1893 @code{[..., (x+y)]} 1894 1895 @item 1896 1897 BINARY_SUBTRACT 1898 1899 @tab 1900 1901 Likewise, but subtract. 1902 1903 @tab 1904 1905 @code{[..., x, y]} 1906 1907 @tab 1908 1909 @code{[..., (x-y)]} 1910 1911 @item 1912 1913 BINARY_MULT 1914 1915 @tab 1916 1917 Likewise, but multiply. 1918 1919 @tab 1920 1921 @code{[..., x, y]} 1922 1923 @tab 1924 1925 @code{[..., (x*y)]} 1926 1927 @item 1928 1929 BINARY_COMPARE_LT 1930 1931 @tab 1932 1933 Compare the top two 1934 elements on the stack 1935 and push a nonzero/zero 1936 if (x<y). 1937 1938 @tab 1939 1940 @code{[..., x, y]} 1941 1942 @tab 1943 1944 @code{[..., (x<y)]} 1945 1946 @item 1947 1948 RECURSE 1949 1950 @tab 1951 1952 Recurse, passing the top 1953 of the stack, and 1954 popping the result. 1955 1956 @tab 1957 1958 @code{[..., x]} 1959 1960 @tab 1961 1962 @code{[..., fn(x)]} 1963 1964 @item 1965 1966 RETURN 1967 1968 @tab 1969 1970 Return the top of the 1971 stack. 1972 1973 @tab 1974 1975 @code{[x]} 1976 1977 @tab 1978 1979 @code{[]} 1980 1981 @item 1982 1983 PUSH_CONST @cite{arg} 1984 1985 @tab 1986 1987 Push an int const. 1988 1989 @tab 1990 1991 @code{[...]} 1992 1993 @tab 1994 1995 @code{[..., arg]} 1996 1997 @item 1998 1999 JUMP_ABS_IF_TRUE @cite{arg} 2000 2001 @tab 2002 2003 Pop; if top of stack was 2004 nonzero, jump to 2005 @code{arg}. 2006 2007 @tab 2008 2009 @code{[..., x]} 2010 2011 @tab 2012 2013 @code{[...]} 2014 2015 @end multitable 2016 2017 2018 Programs can be interpreted, disassembled, and compiled to machine code. 2019 2020 The interpreter reads @code{.toy} scripts. Heres what a simple recursive 2021 factorial program looks like, the script @code{factorial.toy}. 2022 The parser ignores lines beginning with a @cite{#}. 2023 2024 @quotation 2025 2026 @example 2027 # Simple recursive factorial implementation, roughly equivalent to: 2028 # 2029 # int factorial (int arg) 2030 # @{ 2031 # if (arg < 2) 2032 # return arg 2033 # return arg * factorial (arg - 1) 2034 # @} 2035 2036 # Initial state: 2037 # stack: [arg] 2038 2039 # 0: 2040 DUP 2041 # stack: [arg, arg] 2042 2043 # 1: 2044 PUSH_CONST 2 2045 # stack: [arg, arg, 2] 2046 2047 # 2: 2048 BINARY_COMPARE_LT 2049 # stack: [arg, (arg < 2)] 2050 2051 # 3: 2052 JUMP_ABS_IF_TRUE 9 2053 # stack: [arg] 2054 2055 # 4: 2056 DUP 2057 # stack: [arg, arg] 2058 2059 # 5: 2060 PUSH_CONST 1 2061 # stack: [arg, arg, 1] 2062 2063 # 6: 2064 BINARY_SUBTRACT 2065 # stack: [arg, (arg - 1) 2066 2067 # 7: 2068 RECURSE 2069 # stack: [arg, factorial(arg - 1)] 2070 2071 # 8: 2072 BINARY_MULT 2073 # stack: [arg * factorial(arg - 1)] 2074 2075 # 9: 2076 RETURN 2077 @end example 2078 @end quotation 2079 2080 The interpreter is a simple infinite loop with a big @code{switch} statement 2081 based on what the next opcode is: 2082 2083 @quotation 2084 2085 @example 2086 2087 static int 2088 toyvm_function_interpret (toyvm_function *fn, int arg, FILE *trace) 2089 @{ 2090 toyvm_frame frame; 2091 #define PUSH(ARG) (toyvm_frame_push (&frame, (ARG))) 2092 #define POP(ARG) (toyvm_frame_pop (&frame)) 2093 2094 frame.frm_function = fn; 2095 frame.frm_pc = 0; 2096 frame.frm_cur_depth = 0; 2097 2098 PUSH (arg); 2099 2100 while (1) 2101 @{ 2102 toyvm_op *op; 2103 int x, y; 2104 assert (frame.frm_pc < fn->fn_num_ops); 2105 op = &fn->fn_ops[frame.frm_pc++]; 2106 2107 if (trace) 2108 @{ 2109 toyvm_frame_dump_stack (&frame, trace); 2110 toyvm_function_disassemble_op (fn, op, frame.frm_pc, trace); 2111 @} 2112 2113 switch (op->op_opcode) 2114 @{ 2115 /* Ops taking no operand. */ 2116 case DUP: 2117 x = POP (); 2118 PUSH (x); 2119 PUSH (x); 2120 break; 2121 2122 case ROT: 2123 y = POP (); 2124 x = POP (); 2125 PUSH (y); 2126 PUSH (x); 2127 break; 2128 2129 case BINARY_ADD: 2130 y = POP (); 2131 x = POP (); 2132 PUSH (x + y); 2133 break; 2134 2135 case BINARY_SUBTRACT: 2136 y = POP (); 2137 x = POP (); 2138 PUSH (x - y); 2139 break; 2140 2141 case BINARY_MULT: 2142 y = POP (); 2143 x = POP (); 2144 PUSH (x * y); 2145 break; 2146 2147 case BINARY_COMPARE_LT: 2148 y = POP (); 2149 x = POP (); 2150 PUSH (x < y); 2151 break; 2152 2153 case RECURSE: 2154 x = POP (); 2155 x = toyvm_function_interpret (fn, x, trace); 2156 PUSH (x); 2157 break; 2158 2159 case RETURN: 2160 return POP (); 2161 2162 /* Ops taking an operand. */ 2163 case PUSH_CONST: 2164 PUSH (op->op_operand); 2165 break; 2166 2167 case JUMP_ABS_IF_TRUE: 2168 x = POP (); 2169 if (x) 2170 frame.frm_pc = op->op_operand; 2171 break; 2172 2173 default: 2174 assert (0); /* unknown opcode */ 2175 2176 @} /* end of switch on opcode */ 2177 @} /* end of while loop */ 2178 2179 #undef PUSH 2180 #undef POP 2181 @} 2182 2183 @end example 2184 @end quotation 2185 2186 @node Compiling to machine code,Setting things up,Our toy interpreter,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2187 @anchor{intro/tutorial04 compiling-to-machine-code}@anchor{38} 2188 @subsection Compiling to machine code 2189 2190 2191 We want to generate machine code that can be cast to this type and 2192 then directly executed in-process: 2193 2194 @quotation 2195 2196 @example 2197 typedef int (*toyvm_compiled_code) (int); 2198 2199 @end example 2200 @end quotation 2201 2202 The lifetime of the code is tied to that of a @ref{16,,gcc_jit_result *}. 2203 Well handle this by bundling them up in a structure, so that we can 2204 clean them up together by calling @ref{39,,gcc_jit_result_release()}: 2205 2206 @quotation 2207 2208 @example 2209 2210 struct toyvm_compiled_function 2211 @{ 2212 gcc_jit_result *cf_jit_result; 2213 toyvm_compiled_code cf_code; 2214 @}; 2215 2216 @end example 2217 @end quotation 2218 2219 Our compiler isnt very sophisticated; it takes the implementation of 2220 each opcode above, and maps it directly to the operations supported by 2221 the libgccjit API. 2222 2223 How should we handle the stack? In theory we could calculate what the 2224 stack depth will be at each opcode, and optimize away the stack 2225 manipulation by hand. Well see below that libgccjit is able to do 2226 this for us, so well implement stack manipulation 2227 in a direct way, by creating a @code{stack} array and @code{stack_depth} 2228 variables, local within the generated function, equivalent to this C code: 2229 2230 @example 2231 int stack_depth; 2232 int stack[MAX_STACK_DEPTH]; 2233 @end example 2234 2235 Well also have local variables @code{x} and @code{y} for use when implementing 2236 the opcodes, equivalent to this: 2237 2238 @example 2239 int x; 2240 int y; 2241 @end example 2242 2243 This means our compiler has the following state: 2244 2245 @quotation 2246 2247 @example 2248 2249 struct compilation_state 2250 @{ 2251 gcc_jit_context *ctxt; 2252 2253 gcc_jit_type *int_type; 2254 gcc_jit_type *bool_type; 2255 gcc_jit_type *stack_type; /* int[MAX_STACK_DEPTH] */ 2256 2257 gcc_jit_rvalue *const_one; 2258 2259 gcc_jit_function *fn; 2260 gcc_jit_param *param_arg; 2261 gcc_jit_lvalue *stack; 2262 gcc_jit_lvalue *stack_depth; 2263 gcc_jit_lvalue *x; 2264 gcc_jit_lvalue *y; 2265 2266 gcc_jit_location *op_locs[MAX_OPS]; 2267 gcc_jit_block *initial_block; 2268 gcc_jit_block *op_blocks[MAX_OPS]; 2269 2270 @}; 2271 2272 @end example 2273 @end quotation 2274 2275 @node Setting things up,Populating the function,Compiling to machine code,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2276 @anchor{intro/tutorial04 setting-things-up}@anchor{3a} 2277 @subsection Setting things up 2278 2279 2280 First we create our types: 2281 2282 @quotation 2283 2284 @example 2285 state.int_type = 2286 gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_INT); 2287 state.bool_type = 2288 gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_BOOL); 2289 state.stack_type = 2290 gcc_jit_context_new_array_type (state.ctxt, NULL, 2291 state.int_type, MAX_STACK_DEPTH); 2292 2293 @end example 2294 @end quotation 2295 2296 along with extracting a useful @cite{int} constant: 2297 2298 @quotation 2299 2300 @example 2301 state.const_one = gcc_jit_context_one (state.ctxt, state.int_type); 2302 2303 @end example 2304 @end quotation 2305 2306 Well implement push and pop in terms of the @code{stack} array and 2307 @code{stack_depth}. Here are helper functions for adding statements to 2308 a block, implementing pushing and popping values: 2309 2310 @quotation 2311 2312 @example 2313 2314 static void 2315 add_push (compilation_state *state, 2316 gcc_jit_block *block, 2317 gcc_jit_rvalue *rvalue, 2318 gcc_jit_location *loc) 2319 @{ 2320 /* stack[stack_depth] = RVALUE */ 2321 gcc_jit_block_add_assignment ( 2322 block, 2323 loc, 2324 /* stack[stack_depth] */ 2325 gcc_jit_context_new_array_access ( 2326 state->ctxt, 2327 loc, 2328 gcc_jit_lvalue_as_rvalue (state->stack), 2329 gcc_jit_lvalue_as_rvalue (state->stack_depth)), 2330 rvalue); 2331 2332 /* "stack_depth++;". */ 2333 gcc_jit_block_add_assignment_op ( 2334 block, 2335 loc, 2336 state->stack_depth, 2337 GCC_JIT_BINARY_OP_PLUS, 2338 state->const_one); 2339 @} 2340 2341 static void 2342 add_pop (compilation_state *state, 2343 gcc_jit_block *block, 2344 gcc_jit_lvalue *lvalue, 2345 gcc_jit_location *loc) 2346 @{ 2347 /* "--stack_depth;". */ 2348 gcc_jit_block_add_assignment_op ( 2349 block, 2350 loc, 2351 state->stack_depth, 2352 GCC_JIT_BINARY_OP_MINUS, 2353 state->const_one); 2354 2355 /* "LVALUE = stack[stack_depth];". */ 2356 gcc_jit_block_add_assignment ( 2357 block, 2358 loc, 2359 lvalue, 2360 /* stack[stack_depth] */ 2361 gcc_jit_lvalue_as_rvalue ( 2362 gcc_jit_context_new_array_access ( 2363 state->ctxt, 2364 loc, 2365 gcc_jit_lvalue_as_rvalue (state->stack), 2366 gcc_jit_lvalue_as_rvalue (state->stack_depth)))); 2367 @} 2368 2369 @end example 2370 @end quotation 2371 2372 We will support single-stepping through the generated code in the 2373 debugger, so we need to create @ref{3b,,gcc_jit_location} instances, one 2374 per operation in the source code. These will reference the lines of 2375 e.g. @code{factorial.toy}. 2376 2377 @quotation 2378 2379 @example 2380 for (pc = 0; pc < fn->fn_num_ops; pc++) 2381 @{ 2382 toyvm_op *op = &fn->fn_ops[pc]; 2383 2384 state.op_locs[pc] = gcc_jit_context_new_location (state.ctxt, 2385 fn->fn_filename, 2386 op->op_linenum, 2387 0); /* column */ 2388 @} 2389 2390 @end example 2391 @end quotation 2392 2393 Lets create the function itself. As usual, we create its parameter 2394 first, then use the parameter to create the function: 2395 2396 @quotation 2397 2398 @example 2399 state.param_arg = 2400 gcc_jit_context_new_param (state.ctxt, state.op_locs[0], 2401 state.int_type, "arg"); 2402 state.fn = 2403 gcc_jit_context_new_function (state.ctxt, 2404 state.op_locs[0], 2405 GCC_JIT_FUNCTION_EXPORTED, 2406 state.int_type, 2407 funcname, 2408 1, &state.param_arg, 0); 2409 2410 @end example 2411 @end quotation 2412 2413 We create the locals within the function. 2414 2415 @quotation 2416 2417 @example 2418 state.stack = 2419 gcc_jit_function_new_local (state.fn, NULL, 2420 state.stack_type, "stack"); 2421 state.stack_depth = 2422 gcc_jit_function_new_local (state.fn, NULL, 2423 state.int_type, "stack_depth"); 2424 state.x = 2425 gcc_jit_function_new_local (state.fn, NULL, 2426 state.int_type, "x"); 2427 state.y = 2428 gcc_jit_function_new_local (state.fn, NULL, 2429 state.int_type, "y"); 2430 2431 @end example 2432 @end quotation 2433 2434 @node Populating the function,Verifying the control flow graph,Setting things up,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2435 @anchor{intro/tutorial04 populating-the-function}@anchor{3c} 2436 @subsection Populating the function 2437 2438 2439 Theres some one-time initialization, and the API treats the first block 2440 you create as the entrypoint of the function, so we need to create that 2441 block first: 2442 2443 @quotation 2444 2445 @example 2446 state.initial_block = gcc_jit_function_new_block (state.fn, "initial"); 2447 2448 @end example 2449 @end quotation 2450 2451 We can now create blocks for each of the operations. Most of these will 2452 be consolidated into larger blocks when the optimizer runs. 2453 2454 @quotation 2455 2456 @example 2457 for (pc = 0; pc < fn->fn_num_ops; pc++) 2458 @{ 2459 char buf[100]; 2460 sprintf (buf, "instr%i", pc); 2461 state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); 2462 @} 2463 2464 @end example 2465 @end quotation 2466 2467 Now that we have a block it can jump to when its done, we can populate 2468 the initial block: 2469 2470 @quotation 2471 2472 @example 2473 2474 /* "stack_depth = 0;". */ 2475 gcc_jit_block_add_assignment ( 2476 state.initial_block, 2477 state.op_locs[0], 2478 state.stack_depth, 2479 gcc_jit_context_zero (state.ctxt, state.int_type)); 2480 2481 /* "PUSH (arg);". */ 2482 add_push (&state, 2483 state.initial_block, 2484 gcc_jit_param_as_rvalue (state.param_arg), 2485 state.op_locs[0]); 2486 2487 /* ...and jump to insn 0. */ 2488 gcc_jit_block_end_with_jump (state.initial_block, 2489 state.op_locs[0], 2490 state.op_blocks[0]); 2491 2492 @end example 2493 @end quotation 2494 2495 We can now populate the blocks for the individual operations. We loop 2496 through them, adding instructions to their blocks: 2497 2498 @quotation 2499 2500 @example 2501 for (pc = 0; pc < fn->fn_num_ops; pc++) 2502 @{ 2503 gcc_jit_location *loc = state.op_locs[pc]; 2504 2505 gcc_jit_block *block = state.op_blocks[pc]; 2506 gcc_jit_block *next_block = (pc < fn->fn_num_ops 2507 ? state.op_blocks[pc + 1] 2508 : NULL); 2509 2510 toyvm_op *op; 2511 op = &fn->fn_ops[pc]; 2512 2513 @end example 2514 @end quotation 2515 2516 Were going to have another big @code{switch} statement for implementing 2517 the opcodes, this time for compiling them, rather than interpreting 2518 them. Its helpful to have macros for implementing push and pop, so that 2519 we can make the @code{switch} statement thats coming up look as much as 2520 possible like the one above within the interpreter: 2521 2522 @example 2523 2524 #define X_EQUALS_POP()\ 2525 add_pop (&state, block, state.x, loc) 2526 #define Y_EQUALS_POP()\ 2527 add_pop (&state, block, state.y, loc) 2528 #define PUSH_RVALUE(RVALUE)\ 2529 add_push (&state, block, (RVALUE), loc) 2530 #define PUSH_X()\ 2531 PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.x)) 2532 #define PUSH_Y() \ 2533 PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.y)) 2534 2535 @end example 2536 2537 @cartouche 2538 @quotation Note 2539 A particularly clever implementation would have an @emph{identical} 2540 @code{switch} statement shared by the interpreter and the compiler, with 2541 some preprocessor magic. Were not doing that here, for the sake 2542 of simplicity. 2543 @end quotation 2544 @end cartouche 2545 2546 When I first implemented this compiler, I accidentally missed an edit 2547 when copying and pasting the @code{Y_EQUALS_POP} macro, so that popping the 2548 stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y} 2549 uninitialized. 2550 2551 To track this kind of thing down, we can use 2552 @ref{3d,,gcc_jit_block_add_comment()} to add descriptive comments 2553 to the internal representation. This is invaluable when looking through 2554 the generated IR for, say @code{factorial}: 2555 2556 @quotation 2557 2558 @example 2559 2560 gcc_jit_block_add_comment (block, loc, opcode_names[op->op_opcode]); 2561 2562 @end example 2563 @end quotation 2564 2565 We can now write the big @code{switch} statement that implements the 2566 individual opcodes, populating the relevant block with statements: 2567 2568 @quotation 2569 2570 @example 2571 2572 switch (op->op_opcode) 2573 @{ 2574 case DUP: 2575 X_EQUALS_POP (); 2576 PUSH_X (); 2577 PUSH_X (); 2578 break; 2579 2580 case ROT: 2581 Y_EQUALS_POP (); 2582 X_EQUALS_POP (); 2583 PUSH_Y (); 2584 PUSH_X (); 2585 break; 2586 2587 case BINARY_ADD: 2588 Y_EQUALS_POP (); 2589 X_EQUALS_POP (); 2590 PUSH_RVALUE ( 2591 gcc_jit_context_new_binary_op ( 2592 state.ctxt, 2593 loc, 2594 GCC_JIT_BINARY_OP_PLUS, 2595 state.int_type, 2596 gcc_jit_lvalue_as_rvalue (state.x), 2597 gcc_jit_lvalue_as_rvalue (state.y))); 2598 break; 2599 2600 case BINARY_SUBTRACT: 2601 Y_EQUALS_POP (); 2602 X_EQUALS_POP (); 2603 PUSH_RVALUE ( 2604 gcc_jit_context_new_binary_op ( 2605 state.ctxt, 2606 loc, 2607 GCC_JIT_BINARY_OP_MINUS, 2608 state.int_type, 2609 gcc_jit_lvalue_as_rvalue (state.x), 2610 gcc_jit_lvalue_as_rvalue (state.y))); 2611 break; 2612 2613 case BINARY_MULT: 2614 Y_EQUALS_POP (); 2615 X_EQUALS_POP (); 2616 PUSH_RVALUE ( 2617 gcc_jit_context_new_binary_op ( 2618 state.ctxt, 2619 loc, 2620 GCC_JIT_BINARY_OP_MULT, 2621 state.int_type, 2622 gcc_jit_lvalue_as_rvalue (state.x), 2623 gcc_jit_lvalue_as_rvalue (state.y))); 2624 break; 2625 2626 case BINARY_COMPARE_LT: 2627 Y_EQUALS_POP (); 2628 X_EQUALS_POP (); 2629 PUSH_RVALUE ( 2630 /* cast of bool to int */ 2631 gcc_jit_context_new_cast ( 2632 state.ctxt, 2633 loc, 2634 /* (x < y) as a bool */ 2635 gcc_jit_context_new_comparison ( 2636 state.ctxt, 2637 loc, 2638 GCC_JIT_COMPARISON_LT, 2639 gcc_jit_lvalue_as_rvalue (state.x), 2640 gcc_jit_lvalue_as_rvalue (state.y)), 2641 state.int_type)); 2642 break; 2643 2644 case RECURSE: 2645 @{ 2646 X_EQUALS_POP (); 2647 gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (state.x); 2648 PUSH_RVALUE ( 2649 gcc_jit_context_new_call ( 2650 state.ctxt, 2651 loc, 2652 state.fn, 2653 1, &arg)); 2654 break; 2655 @} 2656 2657 case RETURN: 2658 X_EQUALS_POP (); 2659 gcc_jit_block_end_with_return ( 2660 block, 2661 loc, 2662 gcc_jit_lvalue_as_rvalue (state.x)); 2663 break; 2664 2665 /* Ops taking an operand. */ 2666 case PUSH_CONST: 2667 PUSH_RVALUE ( 2668 gcc_jit_context_new_rvalue_from_int ( 2669 state.ctxt, 2670 state.int_type, 2671 op->op_operand)); 2672 break; 2673 2674 case JUMP_ABS_IF_TRUE: 2675 X_EQUALS_POP (); 2676 gcc_jit_block_end_with_conditional ( 2677 block, 2678 loc, 2679 /* "(bool)x". */ 2680 gcc_jit_context_new_cast ( 2681 state.ctxt, 2682 loc, 2683 gcc_jit_lvalue_as_rvalue (state.x), 2684 state.bool_type), 2685 state.op_blocks[op->op_operand], /* on_true */ 2686 next_block); /* on_false */ 2687 break; 2688 2689 default: 2690 assert(0); 2691 @} /* end of switch on opcode */ 2692 2693 @end example 2694 @end quotation 2695 2696 Every block must be terminated, via a call to one of the 2697 @code{gcc_jit_block_end_with_} entrypoints. This has been done for two 2698 of the opcodes, but we need to do it for the other ones, by jumping 2699 to the next block. 2700 2701 @quotation 2702 2703 @example 2704 if (op->op_opcode != JUMP_ABS_IF_TRUE 2705 && op->op_opcode != RETURN) 2706 gcc_jit_block_end_with_jump ( 2707 block, 2708 loc, 2709 next_block); 2710 2711 @end example 2712 @end quotation 2713 2714 This is analogous to simply incrementing the program counter. 2715 2716 @node Verifying the control flow graph,Compiling the context,Populating the function,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2717 @anchor{intro/tutorial04 verifying-the-control-flow-graph}@anchor{3e} 2718 @subsection Verifying the control flow graph 2719 2720 2721 Having finished looping over the blocks, the context is complete. 2722 2723 As before, we can verify that the control flow and statements are sane by 2724 using @ref{33,,gcc_jit_function_dump_to_dot()}: 2725 2726 @example 2727 gcc_jit_function_dump_to_dot (state.fn, "/tmp/factorial.dot"); 2728 @end example 2729 2730 and viewing the result. Note how the label names, comments, and 2731 variable names show up in the dump, to make it easier to spot 2732 errors in our compiler. 2733 2734 @quotation 2735 2736 2737 @float Figure 2738 2739 @image{libgccjit-figures/factorial1,,,image of a control flow graph,png} 2740 2741 @end float 2742 2743 @end quotation 2744 2745 @node Compiling the context,Single-stepping through the generated code,Verifying the control flow graph,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2746 @anchor{intro/tutorial04 compiling-the-context}@anchor{3f} 2747 @subsection Compiling the context 2748 2749 2750 Having finished looping over the blocks and populating them with 2751 statements, the context is complete. 2752 2753 We can now compile it, and extract machine code from the result: 2754 2755 @quotation 2756 @end quotation 2757 2758 We can now run the result: 2759 2760 @quotation 2761 2762 @example 2763 toyvm_compiled_function *compiled_fn 2764 = toyvm_function_compile (fn); 2765 2766 toyvm_compiled_code code = compiled_fn->cf_code; 2767 printf ("compiler result: %d\n", 2768 code (atoi (argv[2]))); 2769 2770 gcc_jit_result_release (compiled_fn->cf_jit_result); 2771 free (compiled_fn); 2772 2773 @end example 2774 @end quotation 2775 2776 @node Single-stepping through the generated code,Examining the generated code,Compiling the context,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2777 @anchor{intro/tutorial04 single-stepping-through-the-generated-code}@anchor{40} 2778 @subsection Single-stepping through the generated code 2779 2780 2781 Its possible to debug the generated code. To do this we need to both: 2782 2783 @quotation 2784 2785 2786 @itemize * 2787 2788 @item 2789 Set up source code locations for our statements, so that we can 2790 meaningfully step through the code. We did this above by 2791 calling @ref{41,,gcc_jit_context_new_location()} and using the 2792 results. 2793 2794 @item 2795 Enable the generation of debugging information, by setting 2796 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 2797 @ref{8,,gcc_jit_context} via 2798 @ref{1b,,gcc_jit_context_set_bool_option()}: 2799 2800 @example 2801 gcc_jit_context_set_bool_option ( 2802 ctxt, 2803 GCC_JIT_BOOL_OPTION_DEBUGINFO, 2804 1); 2805 @end example 2806 @end itemize 2807 @end quotation 2808 2809 Having done this, we can put a breakpoint on the generated function: 2810 2811 @example 2812 $ gdb --args ./toyvm factorial.toy 10 2813 (gdb) break factorial 2814 Function "factorial" not defined. 2815 Make breakpoint pending on future shared library load? (y or [n]) y 2816 Breakpoint 1 (factorial) pending. 2817 (gdb) run 2818 Breakpoint 1, factorial (arg=10) at factorial.toy:14 2819 14 DUP 2820 @end example 2821 2822 Weve set up location information, which references @code{factorial.toy}. 2823 This allows us to use e.g. @code{list} to see where we are in the script: 2824 2825 @example 2826 (gdb) list 2827 9 2828 10 # Initial state: 2829 11 # stack: [arg] 2830 12 2831 13 # 0: 2832 14 DUP 2833 15 # stack: [arg, arg] 2834 16 2835 17 # 1: 2836 18 PUSH_CONST 2 2837 @end example 2838 2839 and to step through the function, examining the data: 2840 2841 @example 2842 (gdb) n 2843 18 PUSH_CONST 2 2844 (gdb) n 2845 22 BINARY_COMPARE_LT 2846 (gdb) print stack 2847 $5 = @{10, 10, 2, 0, -7152, 32767, 0, 0@} 2848 (gdb) print stack_depth 2849 $6 = 3 2850 @end example 2851 2852 Youll see that the parts of the @code{stack} array that havent been 2853 touched yet are uninitialized. 2854 2855 @cartouche 2856 @quotation Note 2857 Turning on optimizations may lead to unpredictable results when 2858 stepping through the generated code: the execution may appear to 2859 jump around the source code. This is analogous to turning up the 2860 optimization level in a regular compiler. 2861 @end quotation 2862 @end cartouche 2863 2864 @node Examining the generated code,Putting it all together,Single-stepping through the generated code,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2865 @anchor{intro/tutorial04 examining-the-generated-code}@anchor{43} 2866 @subsection Examining the generated code 2867 2868 2869 How good is the optimized code? 2870 2871 We can turn up optimizations, by calling 2872 @ref{1e,,gcc_jit_context_set_int_option()} with 2873 @ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 2874 2875 @example 2876 gcc_jit_context_set_int_option ( 2877 ctxt, 2878 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2879 3); 2880 @end example 2881 2882 One of GCCs internal representations is called gimple. A dump of the 2883 initial gimple representation of the code can be seen by setting: 2884 2885 @example 2886 gcc_jit_context_set_bool_option (ctxt, 2887 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 2888 1); 2889 @end example 2890 2891 With optimization on and source locations displayed, this gives: 2892 2893 @c We'll use "c" for gimple dumps 2894 2895 @example 2896 factorial (signed int arg) 2897 @{ 2898 <unnamed type> D.80; 2899 signed int D.81; 2900 signed int D.82; 2901 signed int D.83; 2902 signed int D.84; 2903 signed int D.85; 2904 signed int y; 2905 signed int x; 2906 signed int stack_depth; 2907 signed int stack[8]; 2908 2909 try 2910 @{ 2911 initial: 2912 stack_depth = 0; 2913 stack[stack_depth] = arg; 2914 stack_depth = stack_depth + 1; 2915 goto instr0; 2916 instr0: 2917 /* DUP */: 2918 stack_depth = stack_depth + -1; 2919 x = stack[stack_depth]; 2920 stack[stack_depth] = x; 2921 stack_depth = stack_depth + 1; 2922 stack[stack_depth] = x; 2923 stack_depth = stack_depth + 1; 2924 goto instr1; 2925 instr1: 2926 /* PUSH_CONST */: 2927 stack[stack_depth] = 2; 2928 stack_depth = stack_depth + 1; 2929 goto instr2; 2930 2931 /* etc */ 2932 @end example 2933 2934 You can see the generated machine code in assembly form via: 2935 2936 @example 2937 gcc_jit_context_set_bool_option ( 2938 ctxt, 2939 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 2940 1); 2941 result = gcc_jit_context_compile (ctxt); 2942 @end example 2943 2944 which shows that (on this x86_64 box) the compiler has unrolled the loop 2945 and is using MMX instructions to perform several multiplications 2946 simultaneously: 2947 2948 @example 2949 .file "fake.c" 2950 .text 2951 .Ltext0: 2952 .p2align 4,,15 2953 .globl factorial 2954 .type factorial, @@function 2955 factorial: 2956 .LFB0: 2957 .file 1 "factorial.toy" 2958 .loc 1 14 0 2959 .cfi_startproc 2960 .LVL0: 2961 .L2: 2962 .loc 1 26 0 2963 cmpl $1, %edi 2964 jle .L13 2965 leal -1(%rdi), %edx 2966 movl %edx, %ecx 2967 shrl $2, %ecx 2968 leal 0(,%rcx,4), %esi 2969 testl %esi, %esi 2970 je .L14 2971 cmpl $9, %edx 2972 jbe .L14 2973 leal -2(%rdi), %eax 2974 movl %eax, -16(%rsp) 2975 leal -3(%rdi), %eax 2976 movd -16(%rsp), %xmm0 2977 movl %edi, -16(%rsp) 2978 movl %eax, -12(%rsp) 2979 movd -16(%rsp), %xmm1 2980 xorl %eax, %eax 2981 movl %edx, -16(%rsp) 2982 movd -12(%rsp), %xmm4 2983 movd -16(%rsp), %xmm6 2984 punpckldq %xmm4, %xmm0 2985 movdqa .LC1(%rip), %xmm4 2986 punpckldq %xmm6, %xmm1 2987 punpcklqdq %xmm0, %xmm1 2988 movdqa .LC0(%rip), %xmm0 2989 jmp .L5 2990 # etc - edited for brevity 2991 @end example 2992 2993 This is clearly overkill for a function that will likely overflow the 2994 @code{int} type before the vectorization is worthwhile - but then again, this 2995 is a toy example. 2996 2997 Turning down the optimization level to 2: 2998 2999 @example 3000 gcc_jit_context_set_int_option ( 3001 ctxt, 3002 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3003 3); 3004 @end example 3005 3006 yields this code, which is simple enough to quote in its entirety: 3007 3008 @example 3009 .file "fake.c" 3010 .text 3011 .p2align 4,,15 3012 .globl factorial 3013 .type factorial, @@function 3014 factorial: 3015 .LFB0: 3016 .cfi_startproc 3017 .L2: 3018 cmpl $1, %edi 3019 jle .L8 3020 movl $1, %edx 3021 jmp .L4 3022 .p2align 4,,10 3023 .p2align 3 3024 .L6: 3025 movl %eax, %edi 3026 .L4: 3027 .L5: 3028 leal -1(%rdi), %eax 3029 imull %edi, %edx 3030 cmpl $1, %eax 3031 jne .L6 3032 .L3: 3033 .L7: 3034 imull %edx, %eax 3035 ret 3036 .L8: 3037 movl %edi, %eax 3038 movl $1, %edx 3039 jmp .L7 3040 .cfi_endproc 3041 .LFE0: 3042 .size factorial, .-factorial 3043 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%@{gcc_release@})" 3044 .section .note.GNU-stack,"",@@progbits 3045 @end example 3046 3047 Note that the stack pushing and popping have been eliminated, as has the 3048 recursive call (in favor of an iteration). 3049 3050 @node Putting it all together,Behind the curtain How does our code get optimized?,Examining the generated code,Tutorial part 4 Adding JIT-compilation to a toy interpreter 3051 @anchor{intro/tutorial04 putting-it-all-together}@anchor{44} 3052 @subsection Putting it all together 3053 3054 3055 The complete example can be seen in the source tree at 3056 @code{gcc/jit/docs/examples/tut04-toyvm/toyvm.c} 3057 3058 along with a Makefile and a couple of sample .toy scripts: 3059 3060 @example 3061 $ ls -al 3062 drwxrwxr-x. 2 david david 4096 Sep 19 17:46 . 3063 drwxrwxr-x. 3 david david 4096 Sep 19 15:26 .. 3064 -rw-rw-r--. 1 david david 615 Sep 19 12:43 factorial.toy 3065 -rw-rw-r--. 1 david david 834 Sep 19 13:08 fibonacci.toy 3066 -rw-rw-r--. 1 david david 238 Sep 19 14:22 Makefile 3067 -rw-rw-r--. 1 david david 16457 Sep 19 17:07 toyvm.c 3068 3069 $ make toyvm 3070 g++ -Wall -g -o toyvm toyvm.c -lgccjit 3071 3072 $ ./toyvm factorial.toy 10 3073 interpreter result: 3628800 3074 compiler result: 3628800 3075 3076 $ ./toyvm fibonacci.toy 10 3077 interpreter result: 55 3078 compiler result: 55 3079 @end example 3080 3081 @node Behind the curtain How does our code get optimized?,,Putting it all together,Tutorial part 4 Adding JIT-compilation to a toy interpreter 3082 @anchor{intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{45} 3083 @subsection Behind the curtain: How does our code get optimized? 3084 3085 3086 Our example is done, but you may be wondering about exactly how the 3087 compiler turned what we gave it into the machine code seen above. 3088 3089 We can examine what the compiler is doing in detail by setting: 3090 3091 @example 3092 gcc_jit_context_set_bool_option (state.ctxt, 3093 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 3094 1); 3095 gcc_jit_context_set_bool_option (state.ctxt, 3096 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 3097 1); 3098 @end example 3099 3100 This will dump detailed information about the compilers state to a 3101 directory under @code{/tmp}, and keep it from being cleaned up. 3102 3103 The precise names and their formats of these files is subject to change. 3104 Higher optimization levels lead to more files. 3105 Heres what I saw (edited for brevity; there were almost 200 files): 3106 3107 @example 3108 intermediate files written to /tmp/libgccjit-KPQbGw 3109 $ ls /tmp/libgccjit-KPQbGw/ 3110 fake.c.000i.cgraph 3111 fake.c.000i.type-inheritance 3112 fake.c.004t.gimple 3113 fake.c.007t.omplower 3114 fake.c.008t.lower 3115 fake.c.011t.eh 3116 fake.c.012t.cfg 3117 fake.c.014i.visibility 3118 fake.c.015i.early_local_cleanups 3119 fake.c.016t.ssa 3120 # etc 3121 @end example 3122 3123 The gimple code is converted into Static Single Assignment form, 3124 with annotations for use when generating the debuginfo: 3125 3126 @example 3127 $ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa 3128 @end example 3129 3130 @example 3131 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3132 3133 factorial (signed int arg) 3134 @{ 3135 signed int stack[8]; 3136 signed int stack_depth; 3137 signed int x; 3138 signed int y; 3139 <unnamed type> _20; 3140 signed int _21; 3141 signed int _38; 3142 signed int _44; 3143 signed int _51; 3144 signed int _56; 3145 3146 initial: 3147 stack_depth_3 = 0; 3148 # DEBUG stack_depth => stack_depth_3 3149 stack[stack_depth_3] = arg_5(D); 3150 stack_depth_7 = stack_depth_3 + 1; 3151 # DEBUG stack_depth => stack_depth_7 3152 # DEBUG instr0 => NULL 3153 # DEBUG /* DUP */ => NULL 3154 stack_depth_8 = stack_depth_7 + -1; 3155 # DEBUG stack_depth => stack_depth_8 3156 x_9 = stack[stack_depth_8]; 3157 # DEBUG x => x_9 3158 stack[stack_depth_8] = x_9; 3159 stack_depth_11 = stack_depth_8 + 1; 3160 # DEBUG stack_depth => stack_depth_11 3161 stack[stack_depth_11] = x_9; 3162 stack_depth_13 = stack_depth_11 + 1; 3163 # DEBUG stack_depth => stack_depth_13 3164 # DEBUG instr1 => NULL 3165 # DEBUG /* PUSH_CONST */ => NULL 3166 stack[stack_depth_13] = 2; 3167 3168 /* etc; edited for brevity */ 3169 @end example 3170 3171 We can perhaps better see the code by turning off 3172 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to suppress all those @code{DEBUG} 3173 statements, giving: 3174 3175 @example 3176 $ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa 3177 @end example 3178 3179 @example 3180 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3181 3182 factorial (signed int arg) 3183 @{ 3184 signed int stack[8]; 3185 signed int stack_depth; 3186 signed int x; 3187 signed int y; 3188 <unnamed type> _20; 3189 signed int _21; 3190 signed int _38; 3191 signed int _44; 3192 signed int _51; 3193 signed int _56; 3194 3195 initial: 3196 stack_depth_3 = 0; 3197 stack[stack_depth_3] = arg_5(D); 3198 stack_depth_7 = stack_depth_3 + 1; 3199 stack_depth_8 = stack_depth_7 + -1; 3200 x_9 = stack[stack_depth_8]; 3201 stack[stack_depth_8] = x_9; 3202 stack_depth_11 = stack_depth_8 + 1; 3203 stack[stack_depth_11] = x_9; 3204 stack_depth_13 = stack_depth_11 + 1; 3205 stack[stack_depth_13] = 2; 3206 stack_depth_15 = stack_depth_13 + 1; 3207 stack_depth_16 = stack_depth_15 + -1; 3208 y_17 = stack[stack_depth_16]; 3209 stack_depth_18 = stack_depth_16 + -1; 3210 x_19 = stack[stack_depth_18]; 3211 _20 = x_19 < y_17; 3212 _21 = (signed int) _20; 3213 stack[stack_depth_18] = _21; 3214 stack_depth_23 = stack_depth_18 + 1; 3215 stack_depth_24 = stack_depth_23 + -1; 3216 x_25 = stack[stack_depth_24]; 3217 if (x_25 != 0) 3218 goto <bb 4> (instr9); 3219 else 3220 goto <bb 3> (instr4); 3221 3222 instr4: 3223 /* DUP */: 3224 stack_depth_26 = stack_depth_24 + -1; 3225 x_27 = stack[stack_depth_26]; 3226 stack[stack_depth_26] = x_27; 3227 stack_depth_29 = stack_depth_26 + 1; 3228 stack[stack_depth_29] = x_27; 3229 stack_depth_31 = stack_depth_29 + 1; 3230 stack[stack_depth_31] = 1; 3231 stack_depth_33 = stack_depth_31 + 1; 3232 stack_depth_34 = stack_depth_33 + -1; 3233 y_35 = stack[stack_depth_34]; 3234 stack_depth_36 = stack_depth_34 + -1; 3235 x_37 = stack[stack_depth_36]; 3236 _38 = x_37 - y_35; 3237 stack[stack_depth_36] = _38; 3238 stack_depth_40 = stack_depth_36 + 1; 3239 stack_depth_41 = stack_depth_40 + -1; 3240 x_42 = stack[stack_depth_41]; 3241 _44 = factorial (x_42); 3242 stack[stack_depth_41] = _44; 3243 stack_depth_46 = stack_depth_41 + 1; 3244 stack_depth_47 = stack_depth_46 + -1; 3245 y_48 = stack[stack_depth_47]; 3246 stack_depth_49 = stack_depth_47 + -1; 3247 x_50 = stack[stack_depth_49]; 3248 _51 = x_50 * y_48; 3249 stack[stack_depth_49] = _51; 3250 stack_depth_53 = stack_depth_49 + 1; 3251 3252 # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)> 3253 instr9: 3254 /* RETURN */: 3255 stack_depth_54 = stack_depth_1 + -1; 3256 x_55 = stack[stack_depth_54]; 3257 _56 = x_55; 3258 stack =@{v@} @{CLOBBER@}; 3259 return _56; 3260 3261 @} 3262 @end example 3263 3264 Note in the above how all the @ref{28,,gcc_jit_block} instances we 3265 created have been consolidated into just 3 blocks in GCCs internal 3266 representation: @code{initial}, @code{instr4} and @code{instr9}. 3267 3268 @menu 3269 * Optimizing away stack manipulation:: 3270 * Elimination of tail recursion:: 3271 3272 @end menu 3273 3274 @node Optimizing away stack manipulation,Elimination of tail recursion,,Behind the curtain How does our code get optimized? 3275 @anchor{intro/tutorial04 optimizing-away-stack-manipulation}@anchor{46} 3276 @subsubsection Optimizing away stack manipulation 3277 3278 3279 Recall our simple implementation of stack operations. Lets examine 3280 how the stack operations are optimized away. 3281 3282 After a pass of constant-propagation, the depth of the stack at each 3283 opcode can be determined at compile-time: 3284 3285 @example 3286 $ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1 3287 @end example 3288 3289 @example 3290 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3291 3292 factorial (signed int arg) 3293 @{ 3294 signed int stack[8]; 3295 signed int stack_depth; 3296 signed int x; 3297 signed int y; 3298 <unnamed type> _20; 3299 signed int _21; 3300 signed int _38; 3301 signed int _44; 3302 signed int _51; 3303 3304 initial: 3305 stack[0] = arg_5(D); 3306 x_9 = stack[0]; 3307 stack[0] = x_9; 3308 stack[1] = x_9; 3309 stack[2] = 2; 3310 y_17 = stack[2]; 3311 x_19 = stack[1]; 3312 _20 = x_19 < y_17; 3313 _21 = (signed int) _20; 3314 stack[1] = _21; 3315 x_25 = stack[1]; 3316 if (x_25 != 0) 3317 goto <bb 4> (instr9); 3318 else 3319 goto <bb 3> (instr4); 3320 3321 instr4: 3322 /* DUP */: 3323 x_27 = stack[0]; 3324 stack[0] = x_27; 3325 stack[1] = x_27; 3326 stack[2] = 1; 3327 y_35 = stack[2]; 3328 x_37 = stack[1]; 3329 _38 = x_37 - y_35; 3330 stack[1] = _38; 3331 x_42 = stack[1]; 3332 _44 = factorial (x_42); 3333 stack[1] = _44; 3334 y_48 = stack[1]; 3335 x_50 = stack[0]; 3336 _51 = x_50 * y_48; 3337 stack[0] = _51; 3338 3339 instr9: 3340 /* RETURN */: 3341 x_55 = stack[0]; 3342 x_56 = x_55; 3343 stack =@{v@} @{CLOBBER@}; 3344 return x_56; 3345 3346 @} 3347 @end example 3348 3349 Note how, in the above, all those @code{stack_depth} values are now just 3350 constants: were accessing specific stack locations at each opcode. 3351 3352 The esra pass (Early Scalar Replacement of Aggregates) breaks 3353 out our stack array into individual elements: 3354 3355 @example 3356 $ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra 3357 @end example 3358 3359 @example 3360 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3361 3362 Created a replacement for stack offset: 0, size: 32: stack$0 3363 Created a replacement for stack offset: 32, size: 32: stack$1 3364 Created a replacement for stack offset: 64, size: 32: stack$2 3365 3366 Symbols to be put in SSA form 3367 @{ D.89 D.90 D.91 @} 3368 Incremental SSA update started at block: 0 3369 Number of blocks in CFG: 5 3370 Number of blocks to update: 4 ( 80%) 3371 3372 3373 factorial (signed int arg) 3374 @{ 3375 signed int stack$2; 3376 signed int stack$1; 3377 signed int stack$0; 3378 signed int stack[8]; 3379 signed int stack_depth; 3380 signed int x; 3381 signed int y; 3382 <unnamed type> _20; 3383 signed int _21; 3384 signed int _38; 3385 signed int _44; 3386 signed int _51; 3387 3388 initial: 3389 stack$0_45 = arg_5(D); 3390 x_9 = stack$0_45; 3391 stack$0_39 = x_9; 3392 stack$1_32 = x_9; 3393 stack$2_30 = 2; 3394 y_17 = stack$2_30; 3395 x_19 = stack$1_32; 3396 _20 = x_19 < y_17; 3397 _21 = (signed int) _20; 3398 stack$1_28 = _21; 3399 x_25 = stack$1_28; 3400 if (x_25 != 0) 3401 goto <bb 4> (instr9); 3402 else 3403 goto <bb 3> (instr4); 3404 3405 instr4: 3406 /* DUP */: 3407 x_27 = stack$0_39; 3408 stack$0_22 = x_27; 3409 stack$1_14 = x_27; 3410 stack$2_12 = 1; 3411 y_35 = stack$2_12; 3412 x_37 = stack$1_14; 3413 _38 = x_37 - y_35; 3414 stack$1_10 = _38; 3415 x_42 = stack$1_10; 3416 _44 = factorial (x_42); 3417 stack$1_6 = _44; 3418 y_48 = stack$1_6; 3419 x_50 = stack$0_22; 3420 _51 = x_50 * y_48; 3421 stack$0_1 = _51; 3422 3423 # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)> 3424 instr9: 3425 /* RETURN */: 3426 x_55 = stack$0_52; 3427 x_56 = x_55; 3428 stack =@{v@} @{CLOBBER@}; 3429 return x_56; 3430 3431 @} 3432 @end example 3433 3434 Hence at this point, all those pushes and pops of the stack are now 3435 simply assignments to specific temporary variables. 3436 3437 After some copy propagation, the stack manipulation has been completely 3438 optimized away: 3439 3440 @example 3441 $ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1 3442 @end example 3443 3444 @example 3445 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3446 3447 factorial (signed int arg) 3448 @{ 3449 signed int stack$2; 3450 signed int stack$1; 3451 signed int stack$0; 3452 signed int stack[8]; 3453 signed int stack_depth; 3454 signed int x; 3455 signed int y; 3456 <unnamed type> _20; 3457 signed int _21; 3458 signed int _38; 3459 signed int _44; 3460 signed int _51; 3461 3462 initial: 3463 stack$0_39 = arg_5(D); 3464 _20 = arg_5(D) <= 1; 3465 _21 = (signed int) _20; 3466 if (_21 != 0) 3467 goto <bb 4> (instr9); 3468 else 3469 goto <bb 3> (instr4); 3470 3471 instr4: 3472 /* DUP */: 3473 _38 = arg_5(D) + -1; 3474 _44 = factorial (_38); 3475 _51 = arg_5(D) * _44; 3476 stack$0_1 = _51; 3477 3478 # stack$0_52 = PHI <arg_5(D)(2), _51(3)> 3479 instr9: 3480 /* RETURN */: 3481 stack =@{v@} @{CLOBBER@}; 3482 return stack$0_52; 3483 3484 @} 3485 @end example 3486 3487 Later on, another pass finally eliminated @code{stack_depth} local and the 3488 unused parts of the @cite{stack`} array altogether: 3489 3490 @example 3491 $ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa 3492 @end example 3493 3494 @example 3495 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3496 3497 Released 44 names, 314.29%, removed 44 holes 3498 factorial (signed int arg) 3499 @{ 3500 signed int stack$0; 3501 signed int mult_acc_1; 3502 <unnamed type> _5; 3503 signed int _6; 3504 signed int _7; 3505 signed int mul_tmp_10; 3506 signed int mult_acc_11; 3507 signed int mult_acc_13; 3508 3509 # arg_9 = PHI <arg_8(D)(0)> 3510 # mult_acc_13 = PHI <1(0)> 3511 initial: 3512 3513 <bb 5>: 3514 # arg_4 = PHI <arg_9(2), _7(3)> 3515 # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)> 3516 _5 = arg_4 <= 1; 3517 _6 = (signed int) _5; 3518 if (_6 != 0) 3519 goto <bb 4> (instr9); 3520 else 3521 goto <bb 3> (instr4); 3522 3523 instr4: 3524 /* DUP */: 3525 _7 = arg_4 + -1; 3526 mult_acc_11 = mult_acc_1 * arg_4; 3527 goto <bb 5>; 3528 3529 # stack$0_12 = PHI <arg_4(5)> 3530 instr9: 3531 /* RETURN */: 3532 mul_tmp_10 = mult_acc_1 * stack$0_12; 3533 return mul_tmp_10; 3534 3535 @} 3536 @end example 3537 3538 @node Elimination of tail recursion,,Optimizing away stack manipulation,Behind the curtain How does our code get optimized? 3539 @anchor{intro/tutorial04 elimination-of-tail-recursion}@anchor{47} 3540 @subsubsection Elimination of tail recursion 3541 3542 3543 Another significant optimization is the detection that the call to 3544 @code{factorial} is tail recursion, which can be eliminated in favor of 3545 an iteration: 3546 3547 @example 3548 $ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1 3549 @end example 3550 3551 @example 3552 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3553 3554 3555 Symbols to be put in SSA form 3556 @{ D.88 @} 3557 Incremental SSA update started at block: 0 3558 Number of blocks in CFG: 5 3559 Number of blocks to update: 4 ( 80%) 3560 3561 3562 factorial (signed int arg) 3563 @{ 3564 signed int stack$2; 3565 signed int stack$1; 3566 signed int stack$0; 3567 signed int stack[8]; 3568 signed int stack_depth; 3569 signed int x; 3570 signed int y; 3571 signed int mult_acc_1; 3572 <unnamed type> _20; 3573 signed int _21; 3574 signed int _38; 3575 signed int mul_tmp_44; 3576 signed int mult_acc_51; 3577 3578 # arg_5 = PHI <arg_39(D)(0), _38(3)> 3579 # mult_acc_1 = PHI <1(0), mult_acc_51(3)> 3580 initial: 3581 _20 = arg_5 <= 1; 3582 _21 = (signed int) _20; 3583 if (_21 != 0) 3584 goto <bb 4> (instr9); 3585 else 3586 goto <bb 3> (instr4); 3587 3588 instr4: 3589 /* DUP */: 3590 _38 = arg_5 + -1; 3591 mult_acc_51 = mult_acc_1 * arg_5; 3592 goto <bb 2> (initial); 3593 3594 # stack$0_52 = PHI <arg_5(2)> 3595 instr9: 3596 /* RETURN */: 3597 stack =@{v@} @{CLOBBER@}; 3598 mul_tmp_44 = mult_acc_1 * stack$0_52; 3599 return mul_tmp_44; 3600 3601 @} 3602 @end example 3603 3604 @c Copyright (C) 2015-2022 Free Software Foundation, Inc. 3605 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 3606 @c 3607 @c This is free software: you can redistribute it and/or modify it 3608 @c under the terms of the GNU General Public License as published by 3609 @c the Free Software Foundation, either version 3 of the License, or 3610 @c (at your option) any later version. 3611 @c 3612 @c This program is distributed in the hope that it will be useful, but 3613 @c WITHOUT ANY WARRANTY; without even the implied warranty of 3614 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3615 @c General Public License for more details. 3616 @c 3617 @c You should have received a copy of the GNU General Public License 3618 @c along with this program. If not, see 3619 @c <https://www.gnu.org/licenses/>. 3620 3621 @node Tutorial part 5 Implementing an Ahead-of-Time compiler,,Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial 3622 @anchor{intro/tutorial05 doc}@anchor{48}@anchor{intro/tutorial05 tutorial-part-5-implementing-an-ahead-of-time-compiler}@anchor{49} 3623 @section Tutorial part 5: Implementing an Ahead-of-Time compiler 3624 3625 3626 If you have a pre-existing language frontend thats compatible with 3627 libgccjits license, its possible to hook it up to libgccjit as a 3628 backend. In the previous example we showed 3629 how to do that for in-memory JIT-compilation, but libgccjit can also 3630 compile code directly to a file, allowing you to implement a more 3631 traditional ahead-of-time compiler (JIT is something of a misnomer 3632 for this use-case). 3633 3634 The essential difference is to compile the context using 3635 @ref{4a,,gcc_jit_context_compile_to_file()} rather than 3636 @ref{15,,gcc_jit_context_compile()}. 3637 3638 @menu 3639 * The brainf language:: 3640 * Converting a brainf script to libgccjit IR:: 3641 * Compiling a context to a file:: 3642 * Other forms of ahead-of-time-compilation:: 3643 3644 @end menu 3645 3646 @node The brainf language,Converting a brainf script to libgccjit IR,,Tutorial part 5 Implementing an Ahead-of-Time compiler 3647 @anchor{intro/tutorial05 the-brainf-language}@anchor{4b} 3648 @subsection The brainf language 3649 3650 3651 In this example we use libgccjit to construct an ahead-of-time compiler 3652 for an esoteric programming language that we shall refer to as brainf. 3653 3654 brainf scripts operate on an array of bytes, with a notional data pointer 3655 within the array. 3656 3657 brainf is hard for humans to read, but its trivial to write a parser for 3658 it, as there is no lexing; just a stream of bytes. The operations are: 3659 3660 3661 @multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} 3662 @headitem 3663 3664 Character 3665 3666 @tab 3667 3668 Meaning 3669 3670 @item 3671 3672 @code{>} 3673 3674 @tab 3675 3676 @code{idx += 1} 3677 3678 @item 3679 3680 @code{<} 3681 3682 @tab 3683 3684 @code{idx -= 1} 3685 3686 @item 3687 3688 @code{+} 3689 3690 @tab 3691 3692 @code{data[idx] += 1} 3693 3694 @item 3695 3696 @code{-} 3697 3698 @tab 3699 3700 @code{data[idx] -= 1} 3701 3702 @item 3703 3704 @code{.} 3705 3706 @tab 3707 3708 @code{output (data[idx])} 3709 3710 @item 3711 3712 @code{,} 3713 3714 @tab 3715 3716 @code{data[idx] = input ()} 3717 3718 @item 3719 3720 @code{[} 3721 3722 @tab 3723 3724 loop until @code{data[idx] == 0} 3725 3726 @item 3727 3728 @code{]} 3729 3730 @tab 3731 3732 end of loop 3733 3734 @item 3735 3736 Anything else 3737 3738 @tab 3739 3740 ignored 3741 3742 @end multitable 3743 3744 3745 Unlike the previous example, well implement an ahead-of-time compiler, 3746 which reads @code{.bf} scripts and outputs executables (though it would 3747 be trivial to have it run them JIT-compiled in-process). 3748 3749 Heres what a simple @code{.bf} script looks like: 3750 3751 @quotation 3752 3753 @example 3754 [ 3755 Emit the uppercase alphabet 3756 ] 3757 3758 cell 0 = 26 3759 ++++++++++++++++++++++++++ 3760 3761 cell 1 = 65 3762 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 3763 3764 while cell#0 != 0 3765 [ 3766 > 3767 . emit cell#1 3768 + increment cell@@1 3769 <- decrement cell@@0 3770 ] 3771 @end example 3772 @end quotation 3773 3774 @cartouche 3775 @quotation Note 3776 This example makes use of whitespace and comments for legibility, but 3777 could have been written as: 3778 3779 @example 3780 ++++++++++++++++++++++++++ 3781 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 3782 [>.+<-] 3783 @end example 3784 3785 Its not a particularly useful language, except for providing 3786 compiler-writers with a test case thats easy to parse. The point 3787 is that you can use @ref{4a,,gcc_jit_context_compile_to_file()} 3788 to use libgccjit as a backend for a pre-existing language frontend 3789 (provided that the pre-existing frontend is compatible with libgccjits 3790 license). 3791 @end quotation 3792 @end cartouche 3793 3794 @node Converting a brainf script to libgccjit IR,Compiling a context to a file,The brainf language,Tutorial part 5 Implementing an Ahead-of-Time compiler 3795 @anchor{intro/tutorial05 converting-a-brainf-script-to-libgccjit-ir}@anchor{4c} 3796 @subsection Converting a brainf script to libgccjit IR 3797 3798 3799 As before we write simple code to populate a @ref{8,,gcc_jit_context *}. 3800 3801 @quotation 3802 3803 @example 3804 3805 typedef struct bf_compiler 3806 @{ 3807 const char *filename; 3808 int line; 3809 int column; 3810 3811 gcc_jit_context *ctxt; 3812 3813 gcc_jit_type *void_type; 3814 gcc_jit_type *int_type; 3815 gcc_jit_type *byte_type; 3816 gcc_jit_type *array_type; 3817 3818 gcc_jit_function *func_getchar; 3819 gcc_jit_function *func_putchar; 3820 3821 gcc_jit_function *func; 3822 gcc_jit_block *curblock; 3823 3824 gcc_jit_rvalue *int_zero; 3825 gcc_jit_rvalue *int_one; 3826 gcc_jit_rvalue *byte_zero; 3827 gcc_jit_rvalue *byte_one; 3828 gcc_jit_lvalue *data_cells; 3829 gcc_jit_lvalue *idx; 3830 3831 int num_open_parens; 3832 gcc_jit_block *paren_test[MAX_OPEN_PARENS]; 3833 gcc_jit_block *paren_body[MAX_OPEN_PARENS]; 3834 gcc_jit_block *paren_after[MAX_OPEN_PARENS]; 3835 3836 @} bf_compiler; 3837 3838 /* Bail out, with a message on stderr. */ 3839 3840 static void 3841 fatal_error (bf_compiler *bfc, const char *msg) 3842 @{ 3843 fprintf (stderr, 3844 "%s:%i:%i: %s", 3845 bfc->filename, bfc->line, bfc->column, msg); 3846 abort (); 3847 @} 3848 3849 /* Get "data_cells[idx]" as an lvalue. */ 3850 3851 static gcc_jit_lvalue * 3852 bf_get_current_data (bf_compiler *bfc, gcc_jit_location *loc) 3853 @{ 3854 return gcc_jit_context_new_array_access ( 3855 bfc->ctxt, 3856 loc, 3857 gcc_jit_lvalue_as_rvalue (bfc->data_cells), 3858 gcc_jit_lvalue_as_rvalue (bfc->idx)); 3859 @} 3860 3861 /* Get "data_cells[idx] == 0" as a boolean rvalue. */ 3862 3863 static gcc_jit_rvalue * 3864 bf_current_data_is_zero (bf_compiler *bfc, gcc_jit_location *loc) 3865 @{ 3866 return gcc_jit_context_new_comparison ( 3867 bfc->ctxt, 3868 loc, 3869 GCC_JIT_COMPARISON_EQ, 3870 gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)), 3871 bfc->byte_zero); 3872 @} 3873 3874 /* Compile one bf character. */ 3875 3876 static void 3877 bf_compile_char (bf_compiler *bfc, 3878 unsigned char ch) 3879 @{ 3880 gcc_jit_location *loc = 3881 gcc_jit_context_new_location (bfc->ctxt, 3882 bfc->filename, 3883 bfc->line, 3884 bfc->column); 3885 3886 /* Turn this on to trace execution, by injecting putchar () 3887 of each source char. */ 3888 if (0) 3889 @{ 3890 gcc_jit_rvalue *arg = 3891 gcc_jit_context_new_rvalue_from_int ( 3892 bfc->ctxt, 3893 bfc->int_type, 3894 ch); 3895 gcc_jit_rvalue *call = 3896 gcc_jit_context_new_call (bfc->ctxt, 3897 loc, 3898 bfc->func_putchar, 3899 1, &arg); 3900 gcc_jit_block_add_eval (bfc->curblock, 3901 loc, 3902 call); 3903 @} 3904 3905 switch (ch) 3906 @{ 3907 case '>': 3908 gcc_jit_block_add_comment (bfc->curblock, 3909 loc, 3910 "'>': idx += 1;"); 3911 gcc_jit_block_add_assignment_op (bfc->curblock, 3912 loc, 3913 bfc->idx, 3914 GCC_JIT_BINARY_OP_PLUS, 3915 bfc->int_one); 3916 break; 3917 3918 case '<': 3919 gcc_jit_block_add_comment (bfc->curblock, 3920 loc, 3921 "'<': idx -= 1;"); 3922 gcc_jit_block_add_assignment_op (bfc->curblock, 3923 loc, 3924 bfc->idx, 3925 GCC_JIT_BINARY_OP_MINUS, 3926 bfc->int_one); 3927 break; 3928 3929 case '+': 3930 gcc_jit_block_add_comment (bfc->curblock, 3931 loc, 3932 "'+': data[idx] += 1;"); 3933 gcc_jit_block_add_assignment_op (bfc->curblock, 3934 loc, 3935 bf_get_current_data (bfc, loc), 3936 GCC_JIT_BINARY_OP_PLUS, 3937 bfc->byte_one); 3938 break; 3939 3940 case '-': 3941 gcc_jit_block_add_comment (bfc->curblock, 3942 loc, 3943 "'-': data[idx] -= 1;"); 3944 gcc_jit_block_add_assignment_op (bfc->curblock, 3945 loc, 3946 bf_get_current_data (bfc, loc), 3947 GCC_JIT_BINARY_OP_MINUS, 3948 bfc->byte_one); 3949 break; 3950 3951 case '.': 3952 @{ 3953 gcc_jit_rvalue *arg = 3954 gcc_jit_context_new_cast ( 3955 bfc->ctxt, 3956 loc, 3957 gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)), 3958 bfc->int_type); 3959 gcc_jit_rvalue *call = 3960 gcc_jit_context_new_call (bfc->ctxt, 3961 loc, 3962 bfc->func_putchar, 3963 1, &arg); 3964 gcc_jit_block_add_comment (bfc->curblock, 3965 loc, 3966 "'.': putchar ((int)data[idx]);"); 3967 gcc_jit_block_add_eval (bfc->curblock, 3968 loc, 3969 call); 3970 @} 3971 break; 3972 3973 case ',': 3974 @{ 3975 gcc_jit_rvalue *call = 3976 gcc_jit_context_new_call (bfc->ctxt, 3977 loc, 3978 bfc->func_getchar, 3979 0, NULL); 3980 gcc_jit_block_add_comment ( 3981 bfc->curblock, 3982 loc, 3983 "',': data[idx] = (unsigned char)getchar ();"); 3984 gcc_jit_block_add_assignment (bfc->curblock, 3985 loc, 3986 bf_get_current_data (bfc, loc), 3987 gcc_jit_context_new_cast ( 3988 bfc->ctxt, 3989 loc, 3990 call, 3991 bfc->byte_type)); 3992 @} 3993 break; 3994 3995 case '[': 3996 @{ 3997 gcc_jit_block *loop_test = 3998 gcc_jit_function_new_block (bfc->func, NULL); 3999 gcc_jit_block *on_zero = 4000 gcc_jit_function_new_block (bfc->func, NULL); 4001 gcc_jit_block *on_non_zero = 4002 gcc_jit_function_new_block (bfc->func, NULL); 4003 4004 if (bfc->num_open_parens == MAX_OPEN_PARENS) 4005 fatal_error (bfc, "too many open parens"); 4006 4007 gcc_jit_block_end_with_jump ( 4008 bfc->curblock, 4009 loc, 4010 loop_test); 4011 4012 gcc_jit_block_add_comment ( 4013 loop_test, 4014 loc, 4015 "'['"); 4016 gcc_jit_block_end_with_conditional ( 4017 loop_test, 4018 loc, 4019 bf_current_data_is_zero (bfc, loc), 4020 on_zero, 4021 on_non_zero); 4022 bfc->paren_test[bfc->num_open_parens] = loop_test; 4023 bfc->paren_body[bfc->num_open_parens] = on_non_zero; 4024 bfc->paren_after[bfc->num_open_parens] = on_zero; 4025 bfc->num_open_parens += 1; 4026 bfc->curblock = on_non_zero; 4027 @} 4028 break; 4029 4030 case ']': 4031 @{ 4032 gcc_jit_block_add_comment ( 4033 bfc->curblock, 4034 loc, 4035 "']'"); 4036 4037 if (bfc->num_open_parens == 0) 4038 fatal_error (bfc, "mismatching parens"); 4039 bfc->num_open_parens -= 1; 4040 gcc_jit_block_end_with_jump ( 4041 bfc->curblock, 4042 loc, 4043 bfc->paren_test[bfc->num_open_parens]); 4044 bfc->curblock = bfc->paren_after[bfc->num_open_parens]; 4045 @} 4046 break; 4047 4048 case '\n': 4049 bfc->line +=1; 4050 bfc->column = 0; 4051 break; 4052 @} 4053 4054 if (ch != '\n') 4055 bfc->column += 1; 4056 @} 4057 4058 /* Compile the given .bf file into a gcc_jit_context, containing a 4059 single "main" function suitable for compiling into an executable. */ 4060 4061 gcc_jit_context * 4062 bf_compile (const char *filename) 4063 @{ 4064 bf_compiler bfc; 4065 FILE *f_in; 4066 int ch; 4067 4068 memset (&bfc, 0, sizeof (bfc)); 4069 4070 bfc.filename = filename; 4071 f_in = fopen (filename, "r"); 4072 if (!f_in) 4073 fatal_error (&bfc, "unable to open file"); 4074 bfc.line = 1; 4075 4076 bfc.ctxt = gcc_jit_context_acquire (); 4077 4078 gcc_jit_context_set_int_option ( 4079 bfc.ctxt, 4080 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 4081 3); 4082 gcc_jit_context_set_bool_option ( 4083 bfc.ctxt, 4084 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 4085 0); 4086 gcc_jit_context_set_bool_option ( 4087 bfc.ctxt, 4088 GCC_JIT_BOOL_OPTION_DEBUGINFO, 4089 1); 4090 gcc_jit_context_set_bool_option ( 4091 bfc.ctxt, 4092 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 4093 0); 4094 gcc_jit_context_set_bool_option ( 4095 bfc.ctxt, 4096 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 4097 0); 4098 4099 bfc.void_type = 4100 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_VOID); 4101 bfc.int_type = 4102 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_INT); 4103 bfc.byte_type = 4104 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR); 4105 bfc.array_type = 4106 gcc_jit_context_new_array_type (bfc.ctxt, 4107 NULL, 4108 bfc.byte_type, 4109 30000); 4110 4111 bfc.func_getchar = 4112 gcc_jit_context_new_function (bfc.ctxt, NULL, 4113 GCC_JIT_FUNCTION_IMPORTED, 4114 bfc.int_type, 4115 "getchar", 4116 0, NULL, 4117 0); 4118 4119 gcc_jit_param *param_c = 4120 gcc_jit_context_new_param (bfc.ctxt, NULL, bfc.int_type, "c"); 4121 bfc.func_putchar = 4122 gcc_jit_context_new_function (bfc.ctxt, NULL, 4123 GCC_JIT_FUNCTION_IMPORTED, 4124 bfc.void_type, 4125 "putchar", 4126 1, ¶m_c, 4127 0); 4128 4129 bfc.func = make_main (bfc.ctxt); 4130 bfc.curblock = 4131 gcc_jit_function_new_block (bfc.func, "initial"); 4132 bfc.int_zero = gcc_jit_context_zero (bfc.ctxt, bfc.int_type); 4133 bfc.int_one = gcc_jit_context_one (bfc.ctxt, bfc.int_type); 4134 bfc.byte_zero = gcc_jit_context_zero (bfc.ctxt, bfc.byte_type); 4135 bfc.byte_one = gcc_jit_context_one (bfc.ctxt, bfc.byte_type); 4136 4137 bfc.data_cells = 4138 gcc_jit_context_new_global (bfc.ctxt, NULL, 4139 GCC_JIT_GLOBAL_INTERNAL, 4140 bfc.array_type, 4141 "data_cells"); 4142 bfc.idx = 4143 gcc_jit_function_new_local (bfc.func, NULL, 4144 bfc.int_type, 4145 "idx"); 4146 4147 gcc_jit_block_add_comment (bfc.curblock, 4148 NULL, 4149 "idx = 0;"); 4150 gcc_jit_block_add_assignment (bfc.curblock, 4151 NULL, 4152 bfc.idx, 4153 bfc.int_zero); 4154 4155 bfc.num_open_parens = 0; 4156 4157 while ( EOF != (ch = fgetc (f_in))) 4158 bf_compile_char (&bfc, (unsigned char)ch); 4159 4160 gcc_jit_block_end_with_return (bfc.curblock, NULL, bfc.int_zero); 4161 4162 fclose (f_in); 4163 4164 return bfc.ctxt; 4165 @} 4166 4167 @end example 4168 @end quotation 4169 4170 @node Compiling a context to a file,Other forms of ahead-of-time-compilation,Converting a brainf script to libgccjit IR,Tutorial part 5 Implementing an Ahead-of-Time compiler 4171 @anchor{intro/tutorial05 compiling-a-context-to-a-file}@anchor{4d} 4172 @subsection Compiling a context to a file 4173 4174 4175 Unlike the previous tutorial, this time well compile the context 4176 directly to an executable, using @ref{4a,,gcc_jit_context_compile_to_file()}: 4177 4178 @example 4179 gcc_jit_context_compile_to_file (ctxt, 4180 GCC_JIT_OUTPUT_KIND_EXECUTABLE, 4181 output_file); 4182 @end example 4183 4184 Heres the top-level of the compiler, which is what actually calls into 4185 @ref{4a,,gcc_jit_context_compile_to_file()}: 4186 4187 @quotation 4188 4189 @example 4190 4191 int 4192 main (int argc, char **argv) 4193 @{ 4194 const char *input_file; 4195 const char *output_file; 4196 gcc_jit_context *ctxt; 4197 const char *err; 4198 4199 if (argc != 3) 4200 @{ 4201 fprintf (stderr, "%s: INPUT_FILE OUTPUT_FILE\n", argv[0]); 4202 return 1; 4203 @} 4204 4205 input_file = argv[1]; 4206 output_file = argv[2]; 4207 ctxt = bf_compile (input_file); 4208 4209 gcc_jit_context_compile_to_file (ctxt, 4210 GCC_JIT_OUTPUT_KIND_EXECUTABLE, 4211 output_file); 4212 4213 err = gcc_jit_context_get_first_error (ctxt); 4214 4215 if (err) 4216 @{ 4217 gcc_jit_context_release (ctxt); 4218 return 1; 4219 @} 4220 4221 gcc_jit_context_release (ctxt); 4222 return 0; 4223 @} 4224 4225 @end example 4226 @end quotation 4227 4228 Note how once the context is populated you could trivially instead compile 4229 it to memory using @ref{15,,gcc_jit_context_compile()} and run it in-process 4230 as in the previous tutorial. 4231 4232 To create an executable, we need to export a @code{main} function. Heres 4233 how to create one from the JIT API: 4234 4235 @quotation 4236 4237 @example 4238 4239 /* Make "main" function: 4240 int 4241 main (int argc, char **argv) 4242 @{ 4243 ... 4244 @} 4245 */ 4246 static gcc_jit_function * 4247 make_main (gcc_jit_context *ctxt) 4248 @{ 4249 gcc_jit_type *int_type = 4250 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 4251 gcc_jit_param *param_argc = 4252 gcc_jit_context_new_param (ctxt, NULL, int_type, "argc"); 4253 gcc_jit_type *char_ptr_ptr_type = 4254 gcc_jit_type_get_pointer ( 4255 gcc_jit_type_get_pointer ( 4256 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR))); 4257 gcc_jit_param *param_argv = 4258 gcc_jit_context_new_param (ctxt, NULL, char_ptr_ptr_type, "argv"); 4259 gcc_jit_param *params[2] = @{param_argc, param_argv@}; 4260 gcc_jit_function *func_main = 4261 gcc_jit_context_new_function (ctxt, NULL, 4262 GCC_JIT_FUNCTION_EXPORTED, 4263 int_type, 4264 "main", 4265 2, params, 4266 0); 4267 return func_main; 4268 @} 4269 4270 @end example 4271 @end quotation 4272 4273 @cartouche 4274 @quotation Note 4275 The above implementation ignores @code{argc} and @code{argv}, but you could 4276 make use of them by exposing @code{param_argc} and @code{param_argv} to the 4277 caller. 4278 @end quotation 4279 @end cartouche 4280 4281 Upon compiling this C code, we obtain a bf-to-machine-code compiler; 4282 lets call it @code{bfc}: 4283 4284 @example 4285 $ gcc \ 4286 tut05-bf.c \ 4287 -o bfc \ 4288 -lgccjit 4289 @end example 4290 4291 We can now use @code{bfc} to compile .bf files into machine code executables: 4292 4293 @example 4294 $ ./bfc \ 4295 emit-alphabet.bf \ 4296 a.out 4297 @end example 4298 4299 which we can run directly: 4300 4301 @example 4302 $ ./a.out 4303 ABCDEFGHIJKLMNOPQRSTUVWXYZ 4304 @end example 4305 4306 Success! 4307 4308 We can also inspect the generated executable using standard tools: 4309 4310 @example 4311 $ objdump -d a.out |less 4312 @end example 4313 4314 which shows that libgccjit has managed to optimize the function 4315 somewhat (for example, the runs of 26 and 65 increment operations 4316 have become integer constants 0x1a and 0x41): 4317 4318 @example 4319 0000000000400620 <main>: 4320 400620: 80 3d 39 0a 20 00 00 cmpb $0x0,0x200a39(%rip) # 601060 <data 4321 400627: 74 07 je 400630 <main 4322 400629: eb fe jmp 400629 <main+0x9> 4323 40062b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4324 400630: 48 83 ec 08 sub $0x8,%rsp 4325 400634: 0f b6 05 26 0a 20 00 movzbl 0x200a26(%rip),%eax # 601061 <data_cells+0x1> 4326 40063b: c6 05 1e 0a 20 00 1a movb $0x1a,0x200a1e(%rip) # 601060 <data_cells> 4327 400642: 8d 78 41 lea 0x41(%rax),%edi 4328 400645: 40 88 3d 15 0a 20 00 mov %dil,0x200a15(%rip) # 601061 <data_cells+0x1> 4329 40064c: 0f 1f 40 00 nopl 0x0(%rax) 4330 400650: 40 0f b6 ff movzbl %dil,%edi 4331 400654: e8 87 fe ff ff callq 4004e0 <putchar@@plt> 4332 400659: 0f b6 05 01 0a 20 00 movzbl 0x200a01(%rip),%eax # 601061 <data_cells+0x1> 4333 400660: 80 2d f9 09 20 00 01 subb $0x1,0x2009f9(%rip) # 601060 <data_cells> 4334 400667: 8d 78 01 lea 0x1(%rax),%edi 4335 40066a: 40 88 3d f0 09 20 00 mov %dil,0x2009f0(%rip) # 601061 <data_cells+0x1> 4336 400671: 75 dd jne 400650 <main+0x30> 4337 400673: 31 c0 xor %eax,%eax 4338 400675: 48 83 c4 08 add $0x8,%rsp 4339 400679: c3 retq 4340 40067a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 4341 @end example 4342 4343 We also set up debugging information (via 4344 @ref{41,,gcc_jit_context_new_location()} and 4345 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO}), so its possible to use @code{gdb} 4346 to singlestep through the generated binary and inspect the internal 4347 state @code{idx} and @code{data_cells}: 4348 4349 @example 4350 (gdb) break main 4351 Breakpoint 1 at 0x400790 4352 (gdb) run 4353 Starting program: a.out 4354 4355 Breakpoint 1, 0x0000000000400790 in main (argc=1, argv=0x7fffffffe448) 4356 (gdb) stepi 4357 0x0000000000400797 in main (argc=1, argv=0x7fffffffe448) 4358 (gdb) stepi 4359 0x00000000004007a0 in main (argc=1, argv=0x7fffffffe448) 4360 (gdb) stepi 4361 9 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4362 (gdb) list 4363 4 4364 5 cell 0 = 26 4365 6 ++++++++++++++++++++++++++ 4366 7 4367 8 cell 1 = 65 4368 9 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4369 10 4370 11 while cell#0 != 0 4371 12 [ 4372 13 > 4373 (gdb) n 4374 6 ++++++++++++++++++++++++++ 4375 (gdb) n 4376 9 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4377 (gdb) p idx 4378 $1 = 1 4379 (gdb) p data_cells 4380 $2 = "\032", '\000' <repeats 29998 times> 4381 (gdb) p data_cells[0] 4382 $3 = 26 '\032' 4383 (gdb) p data_cells[1] 4384 $4 = 0 '\000' 4385 (gdb) list 4386 4 4387 5 cell 0 = 26 4388 6 ++++++++++++++++++++++++++ 4389 7 4390 8 cell 1 = 65 4391 9 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4392 10 4393 11 while cell#0 != 0 4394 12 [ 4395 13 > 4396 @end example 4397 4398 @node Other forms of ahead-of-time-compilation,,Compiling a context to a file,Tutorial part 5 Implementing an Ahead-of-Time compiler 4399 @anchor{intro/tutorial05 other-forms-of-ahead-of-time-compilation}@anchor{4e} 4400 @subsection Other forms of ahead-of-time-compilation 4401 4402 4403 The above demonstrates compiling a @ref{8,,gcc_jit_context *} directly 4404 to an executable. Its also possible to compile it to an object file, 4405 and to a dynamic library. See the documentation of 4406 @ref{4a,,gcc_jit_context_compile_to_file()} for more information. 4407 4408 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 4409 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 4410 @c 4411 @c This is free software: you can redistribute it and/or modify it 4412 @c under the terms of the GNU General Public License as published by 4413 @c the Free Software Foundation, either version 3 of the License, or 4414 @c (at your option) any later version. 4415 @c 4416 @c This program is distributed in the hope that it will be useful, but 4417 @c WITHOUT ANY WARRANTY; without even the implied warranty of 4418 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4419 @c General Public License for more details. 4420 @c 4421 @c You should have received a copy of the GNU General Public License 4422 @c along with this program. If not, see 4423 @c <https://www.gnu.org/licenses/>. 4424 4425 @node Topic Reference,C++ bindings for libgccjit,Tutorial,Top 4426 @anchor{topics/index doc}@anchor{4f}@anchor{topics/index topic-reference}@anchor{50} 4427 @chapter Topic Reference 4428 4429 4430 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 4431 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 4432 @c 4433 @c This is free software: you can redistribute it and/or modify it 4434 @c under the terms of the GNU General Public License as published by 4435 @c the Free Software Foundation, either version 3 of the License, or 4436 @c (at your option) any later version. 4437 @c 4438 @c This program is distributed in the hope that it will be useful, but 4439 @c WITHOUT ANY WARRANTY; without even the implied warranty of 4440 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4441 @c General Public License for more details. 4442 @c 4443 @c You should have received a copy of the GNU General Public License 4444 @c along with this program. If not, see 4445 @c <https://www.gnu.org/licenses/>. 4446 4447 @menu 4448 * Compilation contexts:: 4449 * Objects:: 4450 * Types:: 4451 * Expressions:: 4452 * Creating and using functions:: 4453 * Function pointers: Function pointers<2>. 4454 * Source Locations:: 4455 * Compiling a context:: 4456 * ABI and API compatibility:: 4457 * Performance:: 4458 * Using Assembly Language with libgccjit:: 4459 4460 @end menu 4461 4462 @node Compilation contexts,Objects,,Topic Reference 4463 @anchor{topics/contexts doc}@anchor{51}@anchor{topics/contexts compilation-contexts}@anchor{52} 4464 @section Compilation contexts 4465 4466 4467 @geindex gcc_jit_context (C type) 4468 @anchor{topics/contexts c gcc_jit_context}@anchor{8} 4469 @deffn {C Type} gcc_jit_context 4470 @end deffn 4471 4472 The top-level of the API is the @ref{8,,gcc_jit_context} type. 4473 4474 A @ref{8,,gcc_jit_context} instance encapsulates the state of a 4475 compilation. 4476 4477 You can set up options on it, and add types, functions and code. 4478 Invoking @ref{15,,gcc_jit_context_compile()} on it gives you a 4479 @ref{16,,gcc_jit_result}. 4480 4481 @menu 4482 * Lifetime-management:: 4483 * Thread-safety:: 4484 * Error-handling: Error-handling<2>. 4485 * Debugging:: 4486 * Options: Options<2>. 4487 4488 @end menu 4489 4490 @node Lifetime-management,Thread-safety,,Compilation contexts 4491 @anchor{topics/contexts lifetime-management}@anchor{53} 4492 @subsection Lifetime-management 4493 4494 4495 Contexts are the unit of lifetime-management within the API: objects 4496 have their lifetime bounded by the context they are created within, and 4497 cleanup of such objects is done for you when the context is released. 4498 4499 @geindex gcc_jit_context_acquire (C function) 4500 @anchor{topics/contexts c gcc_jit_context_acquire}@anchor{9} 4501 @deffn {C Function} gcc_jit_context *gcc_jit_context_acquire (void) 4502 4503 This function acquires a new @ref{8,,gcc_jit_context *} instance, 4504 which is independent of any others that may be present within this 4505 process. 4506 @end deffn 4507 4508 @geindex gcc_jit_context_release (C function) 4509 @anchor{topics/contexts c gcc_jit_context_release}@anchor{c} 4510 @deffn {C Function} void gcc_jit_context_release (gcc_jit_context@w{ }*ctxt) 4511 4512 This function releases all resources associated with the given context. 4513 Both the context itself and all of its @ref{e,,gcc_jit_object *} 4514 instances are cleaned up. It should be called exactly once on a given 4515 context. 4516 4517 It is invalid to use the context or any of its contextual objects 4518 after calling this. 4519 4520 @example 4521 gcc_jit_context_release (ctxt); 4522 @end example 4523 @end deffn 4524 4525 @geindex gcc_jit_context_new_child_context (C function) 4526 @anchor{topics/contexts c gcc_jit_context_new_child_context}@anchor{54} 4527 @deffn {C Function} gcc_jit_context * gcc_jit_context_new_child_context (gcc_jit_context@w{ }*parent_ctxt) 4528 4529 Given an existing JIT context, create a child context. 4530 4531 The child inherits a copy of all option-settings from the parent. 4532 4533 The child can reference objects created within the parent, but not 4534 vice-versa. 4535 4536 The lifetime of the child context must be bounded by that of the 4537 parent: you should release a child context before releasing the parent 4538 context. 4539 4540 If you use a function from a parent context within a child context, 4541 you have to compile the parent context before you can compile the 4542 child context, and the gcc_jit_result of the parent context must 4543 outlive the gcc_jit_result of the child context. 4544 4545 This allows caching of shared initializations. For example, you could 4546 create types and declarations of global functions in a parent context 4547 once within a process, and then create child contexts whenever a 4548 function or loop becomes hot. Each such child context can be used for 4549 JIT-compiling just one function or loop, but can reference types 4550 and helper functions created within the parent context. 4551 4552 Contexts can be arbitrarily nested, provided the above rules are 4553 followed, but its probably not worth going above 2 or 3 levels, and 4554 there will likely be a performance hit for such nesting. 4555 @end deffn 4556 4557 @node Thread-safety,Error-handling<2>,Lifetime-management,Compilation contexts 4558 @anchor{topics/contexts thread-safety}@anchor{55} 4559 @subsection Thread-safety 4560 4561 4562 Instances of @ref{8,,gcc_jit_context *} created via 4563 @ref{9,,gcc_jit_context_acquire()} are independent from each other: 4564 only one thread may use a given context at once, but multiple threads 4565 could each have their own contexts without needing locks. 4566 4567 Contexts created via @ref{54,,gcc_jit_context_new_child_context()} are 4568 related to their parent context. They can be partitioned by their 4569 ultimate ancestor into independent family trees. Only one thread 4570 within a process may use a given family tree of such contexts at once, 4571 and if youre using multiple threads you should provide your own locking 4572 around entire such context partitions. 4573 4574 @node Error-handling<2>,Debugging,Thread-safety,Compilation contexts 4575 @anchor{topics/contexts error-handling}@anchor{19}@anchor{topics/contexts id1}@anchor{56} 4576 @subsection Error-handling 4577 4578 4579 Various kinds of errors are possible when using the API, such as 4580 mismatched types in an assignment. You can only compile and get code from 4581 a context if no errors occur. 4582 4583 Errors are printed on stderr and can be queried using 4584 @ref{57,,gcc_jit_context_get_first_error()}. 4585 4586 They typically contain the name of the API entrypoint where the error 4587 occurred, and pertinent information on the problem: 4588 4589 @example 4590 ./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *) 4591 @end example 4592 4593 In general, if an error occurs when using an API entrypoint, the 4594 entrypoint returns NULL. You dont have to check everywhere for NULL 4595 results, since the API handles a NULL being passed in for any 4596 argument by issuing another error. This typically leads to a cascade of 4597 followup error messages, but is safe (albeit verbose). The first error 4598 message is usually the one to pay attention to, since it is likely to 4599 be responsible for all of the rest: 4600 4601 @geindex gcc_jit_context_get_first_error (C function) 4602 @anchor{topics/contexts c gcc_jit_context_get_first_error}@anchor{57} 4603 @deffn {C Function} const char * gcc_jit_context_get_first_error (gcc_jit_context@w{ }*ctxt) 4604 4605 Returns the first error message that occurred on the context. 4606 4607 The returned string is valid for the rest of the lifetime of the 4608 context. 4609 4610 If no errors occurred, this will be NULL. 4611 @end deffn 4612 4613 If you are wrapping the C API for a higher-level language that supports 4614 exception-handling, you may instead be interested in the last error that 4615 occurred on the context, so that you can embed this in an exception: 4616 4617 @geindex gcc_jit_context_get_last_error (C function) 4618 @anchor{topics/contexts c gcc_jit_context_get_last_error}@anchor{58} 4619 @deffn {C Function} const char * gcc_jit_context_get_last_error (gcc_jit_context@w{ }*ctxt) 4620 4621 Returns the last error message that occurred on the context. 4622 4623 If no errors occurred, this will be NULL. 4624 4625 If non-NULL, the returned string is only guaranteed to be valid until 4626 the next call to libgccjit relating to this context. 4627 @end deffn 4628 4629 @node Debugging,Options<2>,Error-handling<2>,Compilation contexts 4630 @anchor{topics/contexts debugging}@anchor{59} 4631 @subsection Debugging 4632 4633 4634 @geindex gcc_jit_context_dump_to_file (C function) 4635 @anchor{topics/contexts c gcc_jit_context_dump_to_file}@anchor{5a} 4636 @deffn {C Function} void gcc_jit_context_dump_to_file (gcc_jit_context@w{ }*ctxt, const char@w{ }*path, int@w{ }update_locations) 4637 4638 To help with debugging: dump a C-like representation to the given path, 4639 describing whats been set up on the context. 4640 4641 If update_locations is true, then also set up @ref{3b,,gcc_jit_location} 4642 information throughout the context, pointing at the dump file as if it 4643 were a source file. This may be of use in conjunction with 4644 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to allow stepping through the 4645 code in a debugger. 4646 @end deffn 4647 4648 @geindex gcc_jit_context_set_logfile (C function) 4649 @anchor{topics/contexts c gcc_jit_context_set_logfile}@anchor{5b} 4650 @deffn {C Function} void gcc_jit_context_set_logfile (gcc_jit_context@w{ }*ctxt, FILE@w{ }*logfile, int@w{ }flags, int@w{ }verbosity) 4651 4652 To help with debugging; enable ongoing logging of the contexts 4653 activity to the given file. 4654 4655 For example, the following will enable logging to stderr. 4656 4657 @example 4658 gcc_jit_context_set_logfile (ctxt, stderr, 0, 0); 4659 @end example 4660 4661 Examples of information logged include: 4662 4663 4664 @itemize * 4665 4666 @item 4667 API calls 4668 4669 @item 4670 the various steps involved within compilation 4671 4672 @item 4673 activity on any @ref{16,,gcc_jit_result} instances created by 4674 the context 4675 4676 @item 4677 activity within any child contexts 4678 @end itemize 4679 4680 An example of a log can be seen @ref{5c,,here}, 4681 though the precise format and kinds of information logged is subject 4682 to change. 4683 4684 The caller remains responsible for closing @cite{logfile}, and it must not 4685 be closed until all users are released. In particular, note that 4686 child contexts and @ref{16,,gcc_jit_result} instances created by 4687 the context will use the logfile. 4688 4689 There may a performance cost for logging. 4690 4691 You can turn off logging on @cite{ctxt} by passing @cite{NULL} for @cite{logfile}. 4692 Doing so only affects the context; it does not affect child contexts 4693 or @ref{16,,gcc_jit_result} instances already created by 4694 the context. 4695 4696 The parameters flags and verbosity are reserved for future 4697 expansion, and must be zero for now. 4698 @end deffn 4699 4700 To contrast the above: @ref{5a,,gcc_jit_context_dump_to_file()} dumps the 4701 current state of a context to the given path, whereas 4702 @ref{5b,,gcc_jit_context_set_logfile()} enables on-going logging of 4703 future activies on a context to the given @cite{FILE *}. 4704 4705 @geindex gcc_jit_context_dump_reproducer_to_file (C function) 4706 @anchor{topics/contexts c gcc_jit_context_dump_reproducer_to_file}@anchor{5d} 4707 @deffn {C Function} void gcc_jit_context_dump_reproducer_to_file (gcc_jit_context@w{ }*ctxt, const char@w{ }*path) 4708 4709 Write C source code into @cite{path} that can be compiled into a 4710 self-contained executable (i.e. with libgccjit as the only dependency). 4711 The generated code will attempt to replay the API calls that have been 4712 made into the given context. 4713 4714 This may be useful when debugging the library or client code, for 4715 reducing a complicated recipe for reproducing a bug into a simpler 4716 form. For example, consider client code that parses some source file 4717 into some internal representation, and then walks this IR, calling into 4718 libgccjit. If this encounters a bug, a call to 4719 @cite{gcc_jit_context_dump_reproducer_to_file} will write out C code for 4720 a much simpler executable that performs the equivalent calls into 4721 libgccjit, without needing the client code and its data. 4722 4723 Typically you need to supply @code{-Wno-unused-variable} when 4724 compiling the generated file (since the result of each API call is 4725 assigned to a unique variable within the generated C source, and not 4726 all are necessarily then used). 4727 @end deffn 4728 4729 @geindex gcc_jit_context_enable_dump (C function) 4730 @anchor{topics/contexts c gcc_jit_context_enable_dump}@anchor{5e} 4731 @deffn {C Function} void gcc_jit_context_enable_dump (gcc_jit_context@w{ }*ctxt, const char@w{ }*dumpname, char@w{ }**out_ptr) 4732 4733 Enable the dumping of a specific set of internal state from the 4734 compilation, capturing the result in-memory as a buffer. 4735 4736 Parameter dumpname corresponds to the equivalent gcc command-line 4737 option, without the -fdump- prefix. 4738 For example, to get the equivalent of @code{-fdump-tree-vrp1}, 4739 supply @code{"tree-vrp1"}: 4740 4741 @example 4742 static char *dump_vrp1; 4743 4744 void 4745 create_code (gcc_jit_context *ctxt) 4746 @{ 4747 gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1); 4748 /* (other API calls omitted for brevity) */ 4749 @} 4750 @end example 4751 4752 The context directly stores the dumpname as a @code{(const char *)}, so 4753 the passed string must outlive the context. 4754 4755 @ref{15,,gcc_jit_context_compile()} will capture the dump as a 4756 dynamically-allocated buffer, writing it to @code{*out_ptr}. 4757 4758 The caller becomes responsible for calling: 4759 4760 @example 4761 free (*out_ptr) 4762 @end example 4763 4764 each time that @ref{15,,gcc_jit_context_compile()} is called. 4765 @code{*out_ptr} will be written to, either with the address of a buffer, 4766 or with @code{NULL} if an error occurred. 4767 4768 @cartouche 4769 @quotation Warning 4770 This API entrypoint is likely to be less stable than the others. 4771 In particular, both the precise dumpnames, and the format and content 4772 of the dumps are subject to change. 4773 4774 It exists primarily for writing the librarys own test suite. 4775 @end quotation 4776 @end cartouche 4777 @end deffn 4778 4779 @node Options<2>,,Debugging,Compilation contexts 4780 @anchor{topics/contexts options}@anchor{5f} 4781 @subsection Options 4782 4783 4784 Options present in the initial release of libgccjit were handled using 4785 enums, whereas those added subsequently have their own per-option API 4786 entrypoints. 4787 4788 Adding entrypoints for each new option means that client code that use 4789 the new options can be identified directly from binary metadata, which 4790 would not be possible if we instead extended the various 4791 @code{enum gcc_jit_*_option}. 4792 4793 @menu 4794 * String Options:: 4795 * Boolean options:: 4796 * Integer options:: 4797 * Additional command-line options:: 4798 4799 @end menu 4800 4801 @node String Options,Boolean options,,Options<2> 4802 @anchor{topics/contexts string-options}@anchor{60} 4803 @subsubsection String Options 4804 4805 4806 @geindex gcc_jit_context_set_str_option (C function) 4807 @anchor{topics/contexts c gcc_jit_context_set_str_option}@anchor{61} 4808 @deffn {C Function} void gcc_jit_context_set_str_option (gcc_jit_context@w{ }*ctxt, enum gcc_jit_str_option@w{ }opt, const char@w{ }*value) 4809 4810 Set a string option of the context. 4811 4812 @geindex gcc_jit_str_option (C type) 4813 @anchor{topics/contexts c gcc_jit_str_option}@anchor{62} 4814 @deffn {C Type} enum gcc_jit_str_option 4815 @end deffn 4816 4817 The parameter @code{value} can be NULL. If non-NULL, the call takes a 4818 copy of the underlying string, so it is valid to pass in a pointer to 4819 an on-stack buffer. 4820 4821 There is just one string option specified this way: 4822 4823 @geindex GCC_JIT_STR_OPTION_PROGNAME (C macro) 4824 @anchor{topics/contexts c GCC_JIT_STR_OPTION_PROGNAME}@anchor{63} 4825 @deffn {C Macro} GCC_JIT_STR_OPTION_PROGNAME 4826 4827 The name of the program, for use as a prefix when printing error 4828 messages to stderr. If @cite{NULL}, or default, libgccjit.so is used. 4829 @end deffn 4830 @end deffn 4831 4832 @node Boolean options,Integer options,String Options,Options<2> 4833 @anchor{topics/contexts boolean-options}@anchor{64} 4834 @subsubsection Boolean options 4835 4836 4837 @geindex gcc_jit_context_set_bool_option (C function) 4838 @anchor{topics/contexts c gcc_jit_context_set_bool_option}@anchor{1b} 4839 @deffn {C Function} void gcc_jit_context_set_bool_option (gcc_jit_context@w{ }*ctxt, enum gcc_jit_bool_option@w{ }opt, int@w{ }value) 4840 4841 Set a boolean option of the context. 4842 Zero is false (the default), non-zero is true. 4843 4844 @geindex gcc_jit_bool_option (C type) 4845 @anchor{topics/contexts c gcc_jit_bool_option}@anchor{65} 4846 @deffn {C Type} enum gcc_jit_bool_option 4847 @end deffn 4848 4849 @geindex GCC_JIT_BOOL_OPTION_DEBUGINFO (C macro) 4850 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DEBUGINFO}@anchor{42} 4851 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DEBUGINFO 4852 4853 If true, @ref{15,,gcc_jit_context_compile()} will attempt to do the right 4854 thing so that if you attach a debugger to the process, it will 4855 be able to inspect variables and step through your code. 4856 4857 Note that you cant step through code unless you set up source 4858 location information for the code (by creating and passing in 4859 @ref{3b,,gcc_jit_location} instances). 4860 @end deffn 4861 4862 @geindex GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE (C macro) 4863 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE}@anchor{66} 4864 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE 4865 4866 If true, @ref{15,,gcc_jit_context_compile()} will dump its initial 4867 tree representation of your code to stderr (before any 4868 optimizations). 4869 4870 Heres some sample output (from the @cite{square} example): 4871 4872 @example 4873 <statement_list 0x7f4875a62cc0 4874 type <void_type 0x7f4875a64bd0 VOID 4875 align 8 symtab 0 alias set -1 canonical type 0x7f4875a64bd0 4876 pointer_to_this <pointer_type 0x7f4875a64c78>> 4877 side-effects head 0x7f4875a761e0 tail 0x7f4875a761f8 stmts 0x7f4875a62d20 0x7f4875a62d00 4878 4879 stmt <label_expr 0x7f4875a62d20 type <void_type 0x7f4875a64bd0> 4880 side-effects 4881 arg 0 <label_decl 0x7f4875a79080 entry type <void_type 0x7f4875a64bd0> 4882 VOID file (null) line 0 col 0 4883 align 1 context <function_decl 0x7f4875a77500 square>>> 4884 stmt <return_expr 0x7f4875a62d00 4885 type <integer_type 0x7f4875a645e8 public SI 4886 size <integer_cst 0x7f4875a623a0 constant 32> 4887 unit size <integer_cst 0x7f4875a623c0 constant 4> 4888 align 32 symtab 0 alias set -1 canonical type 0x7f4875a645e8 precision 32 min <integer_cst 0x7f4875a62340 -2147483648> max <integer_cst 0x7f4875a62360 2147483647> 4889 pointer_to_this <pointer_type 0x7f4875a6b348>> 4890 side-effects 4891 arg 0 <modify_expr 0x7f4875a72a78 type <integer_type 0x7f4875a645e8> 4892 side-effects arg 0 <result_decl 0x7f4875a7a000 D.54> 4893 arg 1 <mult_expr 0x7f4875a72a50 type <integer_type 0x7f4875a645e8> 4894 arg 0 <parm_decl 0x7f4875a79000 i> arg 1 <parm_decl 0x7f4875a79000 i>>>>> 4895 @end example 4896 @end deffn 4897 4898 @geindex GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE (C macro) 4899 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}@anchor{1c} 4900 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE 4901 4902 If true, @ref{15,,gcc_jit_context_compile()} will dump the gimple 4903 representation of your code to stderr, before any optimizations 4904 are performed. The dump resembles C code: 4905 4906 @example 4907 square (signed int i) 4908 @{ 4909 signed int D.56; 4910 4911 entry: 4912 D.56 = i * i; 4913 return D.56; 4914 @} 4915 @end example 4916 @end deffn 4917 4918 @geindex GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE (C macro) 4919 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE}@anchor{1d} 4920 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE 4921 4922 If true, @ref{15,,gcc_jit_context_compile()} will dump the final 4923 generated code to stderr, in the form of assembly language: 4924 4925 @example 4926 .file "fake.c" 4927 .text 4928 .globl square 4929 .type square, @@function 4930 square: 4931 .LFB0: 4932 .cfi_startproc 4933 pushq %rbp 4934 .cfi_def_cfa_offset 16 4935 .cfi_offset 6, -16 4936 movq %rsp, %rbp 4937 .cfi_def_cfa_register 6 4938 movl %edi, -4(%rbp) 4939 .L2: 4940 movl -4(%rbp), %eax 4941 imull -4(%rbp), %eax 4942 popq %rbp 4943 .cfi_def_cfa 7, 8 4944 ret 4945 .cfi_endproc 4946 .LFE0: 4947 .size square, .-square 4948 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.1-%@{gcc_release@})" 4949 .section .note.GNU-stack,"",@@progbits 4950 @end example 4951 @end deffn 4952 4953 @geindex GCC_JIT_BOOL_OPTION_DUMP_SUMMARY (C macro) 4954 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_SUMMARY}@anchor{67} 4955 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_SUMMARY 4956 4957 If true, @ref{15,,gcc_jit_context_compile()} will print information to stderr 4958 on the actions it is performing. 4959 @end deffn 4960 4961 @geindex GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING (C macro) 4962 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING}@anchor{68} 4963 @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING 4964 4965 If true, @ref{15,,gcc_jit_context_compile()} will dump copious 4966 amount of information on what its doing to various 4967 files within a temporary directory. Use 4968 @ref{69,,GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES} (see below) to 4969 see the results. The files are intended to be human-readable, 4970 but the exact files and their formats are subject to change. 4971 @end deffn 4972 4973 @geindex GCC_JIT_BOOL_OPTION_SELFCHECK_GC (C macro) 4974 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_SELFCHECK_GC}@anchor{6a} 4975 @deffn {C Macro} GCC_JIT_BOOL_OPTION_SELFCHECK_GC 4976 4977 If true, libgccjit will aggressively run its garbage collector, to 4978 shake out bugs (greatly slowing down the compile). This is likely 4979 to only be of interest to developers @emph{of} the library. It is 4980 used when running the selftest suite. 4981 @end deffn 4982 4983 @geindex GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (C macro) 4984 @anchor{topics/contexts c GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES}@anchor{69} 4985 @deffn {C Macro} GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES 4986 4987 If true, the @ref{8,,gcc_jit_context} will not clean up intermediate files 4988 written to the filesystem, and will display their location on stderr. 4989 @end deffn 4990 @end deffn 4991 4992 @geindex gcc_jit_context_set_bool_allow_unreachable_blocks (C function) 4993 @anchor{topics/contexts c gcc_jit_context_set_bool_allow_unreachable_blocks}@anchor{6b} 4994 @deffn {C Function} void gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context@w{ }*ctxt, int@w{ }bool_value) 4995 4996 By default, libgccjit will issue an error about unreachable blocks 4997 within a function. 4998 4999 This entrypoint can be used to disable that error. 5000 5001 This entrypoint was added in @ref{6c,,LIBGCCJIT_ABI_2}; you can test for 5002 its presence using 5003 5004 @example 5005 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks 5006 @end example 5007 @end deffn 5008 5009 @geindex gcc_jit_context_set_bool_use_external_driver (C function) 5010 @anchor{topics/contexts c gcc_jit_context_set_bool_use_external_driver}@anchor{6d} 5011 @deffn {C Function} void gcc_jit_context_set_bool_use_external_driver (gcc_jit_context@w{ }*ctxt, int@w{ }bool_value) 5012 5013 libgccjit internally generates assembler, and uses driver code 5014 for converting it to other formats (e.g. shared libraries). 5015 5016 By default, libgccjit will use an embedded copy of the driver 5017 code. 5018 5019 This option can be used to instead invoke an external driver executable 5020 as a subprocess. 5021 5022 This entrypoint was added in @ref{6e,,LIBGCCJIT_ABI_5}; you can test for 5023 its presence using 5024 5025 @example 5026 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver 5027 @end example 5028 @end deffn 5029 5030 @geindex gcc_jit_context_set_bool_print_errors_to_stderr (C function) 5031 @anchor{topics/contexts c gcc_jit_context_set_bool_print_errors_to_stderr}@anchor{6f} 5032 @deffn {C Function} void gcc_jit_context_set_bool_print_errors_to_stderr (gcc_jit_context@w{ }*ctxt, int@w{ }enabled) 5033 5034 By default, libgccjit will print errors to stderr. 5035 5036 This entrypoint can be used to disable the printing. 5037 5038 This entrypoint was added in @ref{70,,LIBGCCJIT_ABI_23}; you can test for 5039 its presence using 5040 5041 @example 5042 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_print_errors_to_stderr 5043 @end example 5044 @end deffn 5045 5046 @node Integer options,Additional command-line options,Boolean options,Options<2> 5047 @anchor{topics/contexts integer-options}@anchor{71} 5048 @subsubsection Integer options 5049 5050 5051 @geindex gcc_jit_context_set_int_option (C function) 5052 @anchor{topics/contexts c gcc_jit_context_set_int_option}@anchor{1e} 5053 @deffn {C Function} void gcc_jit_context_set_int_option (gcc_jit_context@w{ }*ctxt, enum gcc_jit_int_option@w{ }opt, int@w{ }value) 5054 5055 Set an integer option of the context. 5056 5057 @geindex gcc_jit_int_option (C type) 5058 @anchor{topics/contexts c gcc_jit_int_option}@anchor{72} 5059 @deffn {C Type} enum gcc_jit_int_option 5060 @end deffn 5061 5062 There is just one integer option specified this way: 5063 5064 @geindex GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL (C macro) 5065 @anchor{topics/contexts c GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}@anchor{1f} 5066 @deffn {C Macro} GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL 5067 5068 How much to optimize the code. 5069 5070 Valid values are 0-3, corresponding to GCCs command-line options 5071 -O0 through -O3. 5072 5073 The default value is 0 (unoptimized). 5074 @end deffn 5075 @end deffn 5076 5077 @node Additional command-line options,,Integer options,Options<2> 5078 @anchor{topics/contexts additional-command-line-options}@anchor{73} 5079 @subsubsection Additional command-line options 5080 5081 5082 @geindex gcc_jit_context_add_command_line_option (C function) 5083 @anchor{topics/contexts c gcc_jit_context_add_command_line_option}@anchor{74} 5084 @deffn {C Function} void gcc_jit_context_add_command_line_option (gcc_jit_context@w{ }*ctxt, const char@w{ }*optname) 5085 5086 Add an arbitrary gcc command-line option to the context, for use 5087 by @ref{15,,gcc_jit_context_compile()} and 5088 @ref{4a,,gcc_jit_context_compile_to_file()}. 5089 5090 The parameter @code{optname} must be non-NULL. The underlying buffer is 5091 copied, so that it does not need to outlive the call. 5092 5093 Extra options added by @cite{gcc_jit_context_add_command_line_option} are 5094 applied @emph{after} the regular options above, potentially overriding them. 5095 Options from parent contexts are inherited by child contexts; options 5096 from the parent are applied @emph{before} those from the child. 5097 5098 For example: 5099 5100 @example 5101 gcc_jit_context_add_command_line_option (ctxt, "-ffast-math"); 5102 gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm"); 5103 @end example 5104 5105 Note that only some options are likely to be meaningful; there is no 5106 frontend within libgccjit, so typically only those affecting 5107 optimization and code-generation are likely to be useful. 5108 5109 This entrypoint was added in @ref{75,,LIBGCCJIT_ABI_1}; you can test for 5110 its presence using 5111 5112 @example 5113 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option 5114 @end example 5115 @end deffn 5116 5117 @geindex gcc_jit_context_add_driver_option (C function) 5118 @anchor{topics/contexts c gcc_jit_context_add_driver_option}@anchor{76} 5119 @deffn {C Function} void gcc_jit_context_add_driver_option (gcc_jit_context@w{ }*ctxt, const char@w{ }*optname) 5120 5121 Add an arbitrary gcc driver option to the context, for use by 5122 @ref{15,,gcc_jit_context_compile()} and 5123 @ref{4a,,gcc_jit_context_compile_to_file()}. 5124 5125 The parameter @code{optname} must be non-NULL. The underlying buffer is 5126 copied, so that it does not need to outlive the call. 5127 5128 Extra options added by @cite{gcc_jit_context_add_driver_option} are 5129 applied @emph{after} all other options potentially overriding them. 5130 Options from parent contexts are inherited by child contexts; options 5131 from the parent are applied @emph{before} those from the child. 5132 5133 For example: 5134 5135 @example 5136 gcc_jit_context_add_driver_option (ctxt, "-lm"); 5137 gcc_jit_context_add_driver_option (ctxt, "-fuse-linker-plugin"); 5138 5139 gcc_jit_context_add_driver_option (ctxt, "obj.o"); 5140 5141 gcc_jit_context_add_driver_option (ctxt, "-L."); 5142 gcc_jit_context_add_driver_option (ctxt, "-lwhatever"); 5143 @end example 5144 5145 Note that only some options are likely to be meaningful; there is no 5146 frontend within libgccjit, so typically only those affecting 5147 assembler and linker are likely to be useful. 5148 5149 This entrypoint was added in @ref{77,,LIBGCCJIT_ABI_11}; you can test for 5150 its presence using 5151 5152 @example 5153 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_driver_option 5154 @end example 5155 @end deffn 5156 5157 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 5158 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 5159 @c 5160 @c This is free software: you can redistribute it and/or modify it 5161 @c under the terms of the GNU General Public License as published by 5162 @c the Free Software Foundation, either version 3 of the License, or 5163 @c (at your option) any later version. 5164 @c 5165 @c This program is distributed in the hope that it will be useful, but 5166 @c WITHOUT ANY WARRANTY; without even the implied warranty of 5167 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5168 @c General Public License for more details. 5169 @c 5170 @c You should have received a copy of the GNU General Public License 5171 @c along with this program. If not, see 5172 @c <https://www.gnu.org/licenses/>. 5173 5174 @node Objects,Types,Compilation contexts,Topic Reference 5175 @anchor{topics/objects doc}@anchor{78}@anchor{topics/objects objects}@anchor{79} 5176 @section Objects 5177 5178 5179 @geindex gcc_jit_object (C type) 5180 @anchor{topics/objects c gcc_jit_object}@anchor{e} 5181 @deffn {C Type} gcc_jit_object 5182 @end deffn 5183 5184 Almost every entity in the API (with the exception of 5185 @ref{8,,gcc_jit_context *} and @ref{16,,gcc_jit_result *}) is a 5186 contextual object, a @ref{e,,gcc_jit_object *} 5187 5188 A JIT object: 5189 5190 @quotation 5191 5192 5193 @itemize * 5194 5195 @item 5196 is associated with a @ref{8,,gcc_jit_context *}. 5197 5198 @item 5199 is automatically cleaned up for you when its context is released so 5200 you dont need to manually track and cleanup all objects, just the 5201 contexts. 5202 @end itemize 5203 @end quotation 5204 5205 Although the API is C-based, there is a form of class hierarchy, which 5206 looks like this: 5207 5208 @example 5209 +- gcc_jit_object 5210 +- gcc_jit_location 5211 +- gcc_jit_type 5212 +- gcc_jit_struct 5213 +- gcc_jit_field 5214 +- gcc_jit_function 5215 +- gcc_jit_block 5216 +- gcc_jit_rvalue 5217 +- gcc_jit_lvalue 5218 +- gcc_jit_param 5219 +- gcc_jit_case 5220 +- gcc_jit_extended_asm 5221 @end example 5222 5223 There are casting methods for upcasting from subclasses to parent classes. 5224 For example, @ref{d,,gcc_jit_type_as_object()}: 5225 5226 @example 5227 gcc_jit_object *obj = gcc_jit_type_as_object (int_type); 5228 @end example 5229 5230 The object base class has the following operations: 5231 5232 @geindex gcc_jit_object_get_context (C function) 5233 @anchor{topics/objects c gcc_jit_object_get_context}@anchor{7a} 5234 @deffn {C Function} gcc_jit_context *gcc_jit_object_get_context (gcc_jit_object@w{ }*obj) 5235 5236 Which context is obj within? 5237 @end deffn 5238 5239 @geindex gcc_jit_object_get_debug_string (C function) 5240 @anchor{topics/objects c gcc_jit_object_get_debug_string}@anchor{f} 5241 @deffn {C Function} const char *gcc_jit_object_get_debug_string (gcc_jit_object@w{ }*obj) 5242 5243 Generate a human-readable description for the given object. 5244 5245 For example, 5246 5247 @example 5248 printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj)); 5249 @end example 5250 5251 might give this text on stdout: 5252 5253 @example 5254 obj: 4.0 * (float)i 5255 @end example 5256 5257 @cartouche 5258 @quotation Note 5259 If you call this on an object, the @cite{const char *} buffer is allocated 5260 and generated on the first call for that object, and the buffer will 5261 have the same lifetime as the object i.e. it will exist until the 5262 objects context is released. 5263 @end quotation 5264 @end cartouche 5265 @end deffn 5266 5267 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 5268 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 5269 @c 5270 @c This is free software: you can redistribute it and/or modify it 5271 @c under the terms of the GNU General Public License as published by 5272 @c the Free Software Foundation, either version 3 of the License, or 5273 @c (at your option) any later version. 5274 @c 5275 @c This program is distributed in the hope that it will be useful, but 5276 @c WITHOUT ANY WARRANTY; without even the implied warranty of 5277 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5278 @c General Public License for more details. 5279 @c 5280 @c You should have received a copy of the GNU General Public License 5281 @c along with this program. If not, see 5282 @c <https://www.gnu.org/licenses/>. 5283 5284 @node Types,Expressions,Objects,Topic Reference 5285 @anchor{topics/types doc}@anchor{7b}@anchor{topics/types types}@anchor{7c} 5286 @section Types 5287 5288 5289 @geindex gcc_jit_type (C type) 5290 @anchor{topics/types c gcc_jit_type}@anchor{a} 5291 @deffn {C Type} gcc_jit_type 5292 5293 gcc_jit_type represents a type within the library. 5294 @end deffn 5295 5296 @geindex gcc_jit_type_as_object (C function) 5297 @anchor{topics/types c gcc_jit_type_as_object}@anchor{d} 5298 @deffn {C Function} gcc_jit_object *gcc_jit_type_as_object (gcc_jit_type@w{ }*type) 5299 5300 Upcast a type to an object. 5301 @end deffn 5302 5303 Types can be created in several ways: 5304 5305 5306 @itemize * 5307 5308 @item 5309 fundamental types can be accessed using 5310 @ref{b,,gcc_jit_context_get_type()}: 5311 5312 @example 5313 gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 5314 @end example 5315 5316 See @ref{b,,gcc_jit_context_get_type()} for the available types. 5317 5318 @item 5319 derived types can be accessed by using functions such as 5320 @ref{7d,,gcc_jit_type_get_pointer()} and @ref{7e,,gcc_jit_type_get_const()}: 5321 5322 @example 5323 gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type)); 5324 gcc_jit_type *int_const_star = gcc_jit_type_get_const (gcc_jit_type_get_pointer (int_type)); 5325 @end example 5326 5327 @item 5328 by creating structures (see below). 5329 @end itemize 5330 5331 @menu 5332 * Standard types:: 5333 * Pointers@comma{} const@comma{} and volatile: Pointers const and volatile. 5334 * Vector types:: 5335 * Structures and unions:: 5336 * Function pointer types:: 5337 * Reflection API:: 5338 5339 @end menu 5340 5341 @node Standard types,Pointers const and volatile,,Types 5342 @anchor{topics/types standard-types}@anchor{7f} 5343 @subsection Standard types 5344 5345 5346 @geindex gcc_jit_context_get_type (C function) 5347 @anchor{topics/types c gcc_jit_context_get_type}@anchor{b} 5348 @deffn {C Function} gcc_jit_type *gcc_jit_context_get_type (gcc_jit_context@w{ }*ctxt, enum gcc_jit_types@w{ }type_) 5349 5350 Access a specific type. The available types are: 5351 5352 5353 @multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} 5354 @headitem 5355 5356 @cite{enum gcc_jit_types} value 5357 5358 @tab 5359 5360 Meaning 5361 5362 @item 5363 5364 @code{GCC_JIT_TYPE_VOID} 5365 5366 @tab 5367 5368 Cs @code{void} type. 5369 5370 @item 5371 5372 @code{GCC_JIT_TYPE_VOID_PTR} 5373 5374 @tab 5375 5376 Cs @code{void *}. 5377 5378 @item 5379 5380 @code{GCC_JIT_TYPE_BOOL} 5381 5382 @tab 5383 5384 C++s @code{bool} type; also C99s 5385 @code{_Bool} type, aka @code{bool} if 5386 using stdbool.h. 5387 5388 @item 5389 5390 @code{GCC_JIT_TYPE_CHAR} 5391 5392 @tab 5393 5394 Cs @code{char} (of some signedness) 5395 5396 @item 5397 5398 @code{GCC_JIT_TYPE_SIGNED_CHAR} 5399 5400 @tab 5401 5402 Cs @code{signed char} 5403 5404 @item 5405 5406 @code{GCC_JIT_TYPE_UNSIGNED_CHAR} 5407 5408 @tab 5409 5410 Cs @code{unsigned char} 5411 5412 @item 5413 5414 @code{GCC_JIT_TYPE_SHORT} 5415 5416 @tab 5417 5418 Cs @code{short} (signed) 5419 5420 @item 5421 5422 @code{GCC_JIT_TYPE_UNSIGNED_SHORT} 5423 5424 @tab 5425 5426 Cs @code{unsigned short} 5427 5428 @item 5429 5430 @code{GCC_JIT_TYPE_INT} 5431 5432 @tab 5433 5434 Cs @code{int} (signed) 5435 5436 @item 5437 5438 @code{GCC_JIT_TYPE_UNSIGNED_INT} 5439 5440 @tab 5441 5442 Cs @code{unsigned int} 5443 5444 @item 5445 5446 @code{GCC_JIT_TYPE_LONG} 5447 5448 @tab 5449 5450 Cs @code{long} (signed) 5451 5452 @item 5453 5454 @code{GCC_JIT_TYPE_UNSIGNED_LONG} 5455 5456 @tab 5457 5458 Cs @code{unsigned long} 5459 5460 @item 5461 5462 @code{GCC_JIT_TYPE_LONG_LONG} 5463 5464 @tab 5465 5466 C99s @code{long long} (signed) 5467 5468 @item 5469 5470 @code{GCC_JIT_TYPE_UNSIGNED_LONG_LONG} 5471 5472 @tab 5473 5474 C99s @code{unsigned long long} 5475 5476 @item 5477 5478 @code{GCC_JIT_TYPE_UINT8_T} 5479 5480 @tab 5481 5482 C99s @code{uint8_t} 5483 5484 @item 5485 5486 @code{GCC_JIT_TYPE_UINT16_T} 5487 5488 @tab 5489 5490 C99s @code{uint16_t} 5491 5492 @item 5493 5494 @code{GCC_JIT_TYPE_UINT32_T} 5495 5496 @tab 5497 5498 C99s @code{uint32_t} 5499 5500 @item 5501 5502 @code{GCC_JIT_TYPE_UINT64_T} 5503 5504 @tab 5505 5506 C99s @code{uint64_t} 5507 5508 @item 5509 5510 @code{GCC_JIT_TYPE_UINT128_T} 5511 5512 @tab 5513 5514 C99s @code{__uint128_t} 5515 5516 @item 5517 5518 @code{GCC_JIT_TYPE_INT8_T} 5519 5520 @tab 5521 5522 C99s @code{int8_t} 5523 5524 @item 5525 5526 @code{GCC_JIT_TYPE_INT16_T} 5527 5528 @tab 5529 5530 C99s @code{int16_t} 5531 5532 @item 5533 5534 @code{GCC_JIT_TYPE_INT32_T} 5535 5536 @tab 5537 5538 C99s @code{int32_t} 5539 5540 @item 5541 5542 @code{GCC_JIT_TYPE_INT64_T} 5543 5544 @tab 5545 5546 C99s @code{int64_t} 5547 5548 @item 5549 5550 @code{GCC_JIT_TYPE_INT128_T} 5551 5552 @tab 5553 5554 C99s @code{__int128_t} 5555 5556 @item 5557 5558 @code{GCC_JIT_TYPE_FLOAT} 5559 5560 @tab 5561 5562 @item 5563 5564 @code{GCC_JIT_TYPE_DOUBLE} 5565 5566 @tab 5567 5568 @item 5569 5570 @code{GCC_JIT_TYPE_LONG_DOUBLE} 5571 5572 @tab 5573 5574 @item 5575 5576 @code{GCC_JIT_TYPE_CONST_CHAR_PTR} 5577 5578 @tab 5579 5580 C type: @code{(const char *)} 5581 5582 @item 5583 5584 @code{GCC_JIT_TYPE_SIZE_T} 5585 5586 @tab 5587 5588 Cs @code{size_t} type 5589 5590 @item 5591 5592 @code{GCC_JIT_TYPE_FILE_PTR} 5593 5594 @tab 5595 5596 C type: @code{(FILE *)} 5597 5598 @item 5599 5600 @code{GCC_JIT_TYPE_COMPLEX_FLOAT} 5601 5602 @tab 5603 5604 C99s @code{_Complex float} 5605 5606 @item 5607 5608 @code{GCC_JIT_TYPE_COMPLEX_DOUBLE} 5609 5610 @tab 5611 5612 C99s @code{_Complex double} 5613 5614 @item 5615 5616 @code{GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE} 5617 5618 @tab 5619 5620 C99s @code{_Complex long double} 5621 5622 @end multitable 5623 5624 @end deffn 5625 5626 @geindex gcc_jit_context_get_int_type (C function) 5627 @anchor{topics/types c gcc_jit_context_get_int_type}@anchor{80} 5628 @deffn {C Function} gcc_jit_type * gcc_jit_context_get_int_type (gcc_jit_context@w{ }*ctxt, int@w{ }num_bytes, int@w{ }is_signed) 5629 5630 Access the integer type of the given size. 5631 @end deffn 5632 5633 @node Pointers const and volatile,Vector types,Standard types,Types 5634 @anchor{topics/types pointers-const-and-volatile}@anchor{81} 5635 @subsection Pointers, @cite{const}, and @cite{volatile} 5636 5637 5638 @geindex gcc_jit_type_get_pointer (C function) 5639 @anchor{topics/types c gcc_jit_type_get_pointer}@anchor{7d} 5640 @deffn {C Function} gcc_jit_type *gcc_jit_type_get_pointer (gcc_jit_type@w{ }*type) 5641 5642 Given type T, get type T*. 5643 @end deffn 5644 5645 @geindex gcc_jit_type_get_const (C function) 5646 @anchor{topics/types c gcc_jit_type_get_const}@anchor{7e} 5647 @deffn {C Function} gcc_jit_type *gcc_jit_type_get_const (gcc_jit_type@w{ }*type) 5648 5649 Given type T, get type const T. 5650 @end deffn 5651 5652 @geindex gcc_jit_type_get_volatile (C function) 5653 @anchor{topics/types c gcc_jit_type_get_volatile}@anchor{82} 5654 @deffn {C Function} gcc_jit_type *gcc_jit_type_get_volatile (gcc_jit_type@w{ }*type) 5655 5656 Given type T, get type volatile T. 5657 @end deffn 5658 5659 @geindex gcc_jit_context_new_array_type (C function) 5660 @anchor{topics/types c gcc_jit_context_new_array_type}@anchor{83} 5661 @deffn {C Function} gcc_jit_type * gcc_jit_context_new_array_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*element_type, int@w{ }num_elements) 5662 5663 Given non-@cite{void} type T, get type T[N] (for a constant N). 5664 @end deffn 5665 5666 @geindex gcc_jit_type_get_aligned (C function) 5667 @anchor{topics/types c gcc_jit_type_get_aligned}@anchor{84} 5668 @deffn {C Function} gcc_jit_type * gcc_jit_type_get_aligned (gcc_jit_type@w{ }*type, size_t@w{ }alignment_in_bytes) 5669 5670 Given non-@cite{void} type T, get type: 5671 5672 @example 5673 T __attribute__ ((aligned (ALIGNMENT_IN_BYTES))) 5674 @end example 5675 5676 The alignment must be a power of two. 5677 5678 This entrypoint was added in @ref{85,,LIBGCCJIT_ABI_7}; you can test for 5679 its presence using 5680 5681 @example 5682 #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned 5683 @end example 5684 @end deffn 5685 5686 @node Vector types,Structures and unions,Pointers const and volatile,Types 5687 @anchor{topics/types vector-types}@anchor{86} 5688 @subsection Vector types 5689 5690 5691 @geindex gcc_jit_type_get_vector (C function) 5692 @anchor{topics/types c gcc_jit_type_get_vector}@anchor{87} 5693 @deffn {C Function} gcc_jit_type * gcc_jit_type_get_vector (gcc_jit_type@w{ }*type, size_t@w{ }num_units) 5694 5695 Given type T, get type: 5696 5697 @example 5698 T __attribute__ ((vector_size (sizeof(T) * num_units)) 5699 @end example 5700 5701 T must be integral or floating point; num_units must be a power of two. 5702 5703 This can be used to construct a vector type in which operations 5704 are applied element-wise. The compiler will automatically 5705 use SIMD instructions where possible. See: 5706 @indicateurl{https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html} 5707 5708 For example, assuming 4-byte @code{ints}, then: 5709 5710 @example 5711 typedef int v4si __attribute__ ((vector_size (16))); 5712 @end example 5713 5714 can be obtained using: 5715 5716 @example 5717 gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, 5718 GCC_JIT_TYPE_INT); 5719 gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4); 5720 @end example 5721 5722 This API entrypoint was added in @ref{88,,LIBGCCJIT_ABI_8}; you can test 5723 for its presence using 5724 5725 @example 5726 #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector 5727 @end example 5728 5729 Vector rvalues can be generated using 5730 @ref{89,,gcc_jit_context_new_rvalue_from_vector()}. 5731 @end deffn 5732 5733 @node Structures and unions,Function pointer types,Vector types,Types 5734 @anchor{topics/types structures-and-unions}@anchor{8a} 5735 @subsection Structures and unions 5736 5737 5738 @geindex gcc_jit_struct (C type) 5739 @anchor{topics/types c gcc_jit_struct}@anchor{8b} 5740 @deffn {C Type} gcc_jit_struct 5741 @end deffn 5742 5743 A compound type analagous to a C @cite{struct}. 5744 5745 @geindex gcc_jit_field (C type) 5746 @anchor{topics/types c gcc_jit_field}@anchor{8c} 5747 @deffn {C Type} gcc_jit_field 5748 @end deffn 5749 5750 A field within a @ref{8b,,gcc_jit_struct}. 5751 5752 You can model C @cite{struct} types by creating @ref{8b,,gcc_jit_struct} and 5753 @ref{8c,,gcc_jit_field} instances, in either order: 5754 5755 5756 @itemize * 5757 5758 @item 5759 by creating the fields, then the structure. For example, to model: 5760 5761 @example 5762 struct coord @{double x; double y; @}; 5763 @end example 5764 5765 you could call: 5766 5767 @example 5768 gcc_jit_field *field_x = 5769 gcc_jit_context_new_field (ctxt, NULL, double_type, "x"); 5770 gcc_jit_field *field_y = 5771 gcc_jit_context_new_field (ctxt, NULL, double_type, "y"); 5772 gcc_jit_field *fields[2] = @{field_x, field_y@}; 5773 gcc_jit_struct *coord = 5774 gcc_jit_context_new_struct_type (ctxt, NULL, "coord", 2, fields); 5775 @end example 5776 5777 @item 5778 by creating the structure, then populating it with fields, typically 5779 to allow modelling self-referential structs such as: 5780 5781 @example 5782 struct node @{ int m_hash; struct node *m_next; @}; 5783 @end example 5784 5785 like this: 5786 5787 @example 5788 gcc_jit_type *node = 5789 gcc_jit_context_new_opaque_struct (ctxt, NULL, "node"); 5790 gcc_jit_type *node_ptr = 5791 gcc_jit_type_get_pointer (node); 5792 gcc_jit_field *field_hash = 5793 gcc_jit_context_new_field (ctxt, NULL, int_type, "m_hash"); 5794 gcc_jit_field *field_next = 5795 gcc_jit_context_new_field (ctxt, NULL, node_ptr, "m_next"); 5796 gcc_jit_field *fields[2] = @{field_hash, field_next@}; 5797 gcc_jit_struct_set_fields (node, NULL, 2, fields); 5798 @end example 5799 @end itemize 5800 5801 @geindex gcc_jit_context_new_field (C function) 5802 @anchor{topics/types c gcc_jit_context_new_field}@anchor{8d} 5803 @deffn {C Function} gcc_jit_field * gcc_jit_context_new_field (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, const char@w{ }*name) 5804 5805 Construct a new field, with the given type and name. 5806 5807 The parameter @code{type} must be non-@cite{void}. 5808 5809 The parameter @code{name} must be non-NULL. The call takes a copy of the 5810 underlying string, so it is valid to pass in a pointer to an on-stack 5811 buffer. 5812 @end deffn 5813 5814 @geindex gcc_jit_context_new_bitfield (C function) 5815 @anchor{topics/types c gcc_jit_context_new_bitfield}@anchor{8e} 5816 @deffn {C Function} gcc_jit_field * gcc_jit_context_new_bitfield (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, int@w{ }width, const char@w{ }*name) 5817 5818 Construct a new bit field, with the given type width and name. 5819 5820 The parameter @code{name} must be non-NULL. The call takes a copy of the 5821 underlying string, so it is valid to pass in a pointer to an on-stack 5822 buffer. 5823 5824 The parameter @code{type} must be an integer type. 5825 5826 The parameter @code{width} must be a positive integer that does not exceed the 5827 size of @code{type}. 5828 5829 This API entrypoint was added in @ref{8f,,LIBGCCJIT_ABI_12}; you can test 5830 for its presence using 5831 5832 @example 5833 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield 5834 @end example 5835 @end deffn 5836 5837 @geindex gcc_jit_field_as_object (C function) 5838 @anchor{topics/types c gcc_jit_field_as_object}@anchor{90} 5839 @deffn {C Function} gcc_jit_object * gcc_jit_field_as_object (gcc_jit_field@w{ }*field) 5840 5841 Upcast from field to object. 5842 @end deffn 5843 5844 @geindex gcc_jit_context_new_struct_type (C function) 5845 @anchor{topics/types c gcc_jit_context_new_struct_type}@anchor{91} 5846 @deffn {C Function} gcc_jit_struct *gcc_jit_context_new_struct_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*name, int@w{ }num_fields, gcc_jit_field@w{ }**fields) 5847 5848 @quotation 5849 5850 Construct a new struct type, with the given name and fields. 5851 5852 The parameter @code{name} must be non-NULL. The call takes a copy of 5853 the underlying string, so it is valid to pass in a pointer to an 5854 on-stack buffer. 5855 @end quotation 5856 @end deffn 5857 5858 @geindex gcc_jit_context_new_opaque_struct (C function) 5859 @anchor{topics/types c gcc_jit_context_new_opaque_struct}@anchor{92} 5860 @deffn {C Function} gcc_jit_struct * gcc_jit_context_new_opaque_struct (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*name) 5861 5862 Construct a new struct type, with the given name, but without 5863 specifying the fields. The fields can be omitted (in which case the 5864 size of the struct is not known), or later specified using 5865 @ref{93,,gcc_jit_struct_set_fields()}. 5866 5867 The parameter @code{name} must be non-NULL. The call takes a copy of 5868 the underlying string, so it is valid to pass in a pointer to an 5869 on-stack buffer. 5870 @end deffn 5871 5872 @geindex gcc_jit_struct_as_type (C function) 5873 @anchor{topics/types c gcc_jit_struct_as_type}@anchor{94} 5874 @deffn {C Function} gcc_jit_type * gcc_jit_struct_as_type (gcc_jit_struct@w{ }*struct_type) 5875 5876 Upcast from struct to type. 5877 @end deffn 5878 5879 @geindex gcc_jit_struct_set_fields (C function) 5880 @anchor{topics/types c gcc_jit_struct_set_fields}@anchor{93} 5881 @deffn {C Function} void gcc_jit_struct_set_fields (gcc_jit_struct@w{ }*struct_type, gcc_jit_location@w{ }*loc, int@w{ }num_fields, gcc_jit_field@w{ }**fields) 5882 5883 Populate the fields of a formerly-opaque struct type. 5884 5885 This can only be called once on a given struct type. 5886 @end deffn 5887 5888 @geindex gcc_jit_context_new_union_type (C function) 5889 @anchor{topics/types c gcc_jit_context_new_union_type}@anchor{95} 5890 @deffn {C Function} gcc_jit_type * gcc_jit_context_new_union_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*name, int@w{ }num_fields, gcc_jit_field@w{ }**fields) 5891 5892 Construct a new union type, with the given name and fields. 5893 5894 The parameter @code{name} must be non-NULL. It is copied, so the input 5895 buffer does not need to outlive the call. 5896 5897 Example of use: 5898 5899 @example 5900 5901 union int_or_float 5902 @{ 5903 int as_int; 5904 float as_float; 5905 @}; 5906 5907 void 5908 create_code (gcc_jit_context *ctxt, void *user_data) 5909 @{ 5910 /* Let's try to inject the equivalent of: 5911 float 5912 test_union (int i) 5913 @{ 5914 union int_or_float u; 5915 u.as_int = i; 5916 return u.as_float; 5917 @} 5918 */ 5919 gcc_jit_type *int_type = 5920 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 5921 gcc_jit_type *float_type = 5922 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); 5923 gcc_jit_field *as_int = 5924 gcc_jit_context_new_field (ctxt, 5925 NULL, 5926 int_type, 5927 "as_int"); 5928 gcc_jit_field *as_float = 5929 gcc_jit_context_new_field (ctxt, 5930 NULL, 5931 float_type, 5932 "as_float"); 5933 gcc_jit_field *fields[] = @{as_int, as_float@}; 5934 gcc_jit_type *union_type = 5935 gcc_jit_context_new_union_type (ctxt, NULL, 5936 "int_or_float", 2, fields); 5937 5938 /* Build the test function. */ 5939 gcc_jit_param *param_i = 5940 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 5941 gcc_jit_function *test_fn = 5942 gcc_jit_context_new_function (ctxt, NULL, 5943 GCC_JIT_FUNCTION_EXPORTED, 5944 float_type, 5945 "test_union", 5946 1, ¶m_i, 5947 0); 5948 5949 gcc_jit_lvalue *u = 5950 gcc_jit_function_new_local (test_fn, NULL, 5951 union_type, "u"); 5952 5953 gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); 5954 5955 /* u.as_int = i; */ 5956 gcc_jit_block_add_assignment ( 5957 block, 5958 NULL, 5959 /* "u.as_int = ..." */ 5960 gcc_jit_lvalue_access_field (u, 5961 NULL, 5962 as_int), 5963 gcc_jit_param_as_rvalue (param_i)); 5964 5965 /* return u.as_float; */ 5966 gcc_jit_block_end_with_return ( 5967 block, NULL, 5968 gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (u), 5969 NULL, 5970 as_float)); 5971 @} 5972 5973 @end example 5974 @end deffn 5975 5976 @node Function pointer types,Reflection API,Structures and unions,Types 5977 @anchor{topics/types function-pointer-types}@anchor{96} 5978 @subsection Function pointer types 5979 5980 5981 Function pointer types can be created using 5982 @ref{97,,gcc_jit_context_new_function_ptr_type()}. 5983 5984 @node Reflection API,,Function pointer types,Types 5985 @anchor{topics/types reflection-api}@anchor{98} 5986 @subsection Reflection API 5987 5988 5989 @geindex gcc_jit_type_dyncast_array (C function) 5990 @anchor{topics/types c gcc_jit_type_dyncast_array}@anchor{99} 5991 @deffn {C Function} gcc_jit_type * gcc_jit_type_dyncast_array (gcc_jit_type@w{ }*type) 5992 5993 Get the element type of an array type or NULL if its not an array. 5994 @end deffn 5995 5996 @geindex gcc_jit_type_is_bool (C function) 5997 @anchor{topics/types c gcc_jit_type_is_bool}@anchor{9a} 5998 @deffn {C Function} int gcc_jit_type_is_bool (gcc_jit_type@w{ }*type) 5999 6000 Return non-zero if the type is a bool. 6001 @end deffn 6002 6003 @geindex gcc_jit_type_dyncast_function_ptr_type (C function) 6004 @anchor{topics/types c gcc_jit_type_dyncast_function_ptr_type}@anchor{9b} 6005 @deffn {C Function} gcc_jit_function_type * gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type@w{ }*type) 6006 6007 Return the function type if it is one or NULL. 6008 @end deffn 6009 6010 @geindex gcc_jit_function_type_get_return_type (C function) 6011 @anchor{topics/types c gcc_jit_function_type_get_return_type}@anchor{9c} 6012 @deffn {C Function} gcc_jit_type * gcc_jit_function_type_get_return_type (gcc_jit_function_type@w{ }*function_type) 6013 6014 Given a function type, return its return type. 6015 @end deffn 6016 6017 @geindex gcc_jit_function_type_get_param_count (C function) 6018 @anchor{topics/types c gcc_jit_function_type_get_param_count}@anchor{9d} 6019 @deffn {C Function} size_t gcc_jit_function_type_get_param_count (gcc_jit_function_type@w{ }*function_type) 6020 6021 Given a function type, return its number of parameters. 6022 @end deffn 6023 6024 @geindex gcc_jit_function_type_get_param_type (C function) 6025 @anchor{topics/types c gcc_jit_function_type_get_param_type}@anchor{9e} 6026 @deffn {C Function} gcc_jit_type * gcc_jit_function_type_get_param_type (gcc_jit_function_type@w{ }*function_type, size_t@w{ }index) 6027 6028 Given a function type, return the type of the specified parameter. 6029 @end deffn 6030 6031 @geindex gcc_jit_type_is_integral (C function) 6032 @anchor{topics/types c gcc_jit_type_is_integral}@anchor{9f} 6033 @deffn {C Function} int gcc_jit_type_is_integral (gcc_jit_type@w{ }*type) 6034 6035 Return non-zero if the type is an integral. 6036 @end deffn 6037 6038 @geindex gcc_jit_type_is_pointer (C function) 6039 @anchor{topics/types c gcc_jit_type_is_pointer}@anchor{a0} 6040 @deffn {C Function} gcc_jit_type * gcc_jit_type_is_pointer (gcc_jit_type@w{ }*type) 6041 6042 Return the type pointed by the pointer type or NULL if its not a pointer. 6043 @end deffn 6044 6045 @geindex gcc_jit_type_dyncast_vector (C function) 6046 @anchor{topics/types c gcc_jit_type_dyncast_vector}@anchor{a1} 6047 @deffn {C Function} gcc_jit_vector_type * gcc_jit_type_dyncast_vector (gcc_jit_type@w{ }*type) 6048 6049 Given a type, return a dynamic cast to a vector type or NULL. 6050 @end deffn 6051 6052 @geindex gcc_jit_type_is_struct (C function) 6053 @anchor{topics/types c gcc_jit_type_is_struct}@anchor{a2} 6054 @deffn {C Function} gcc_jit_struct * gcc_jit_type_is_struct (gcc_jit_type@w{ }*type) 6055 6056 Given a type, return a dynamic cast to a struct type or NULL. 6057 @end deffn 6058 6059 @geindex gcc_jit_vector_type_get_num_units (C function) 6060 @anchor{topics/types c gcc_jit_vector_type_get_num_units}@anchor{a3} 6061 @deffn {C Function} size_t gcc_jit_vector_type_get_num_units (gcc_jit_vector_type@w{ }*vector_type) 6062 6063 Given a vector type, return the number of units it contains. 6064 @end deffn 6065 6066 @geindex gcc_jit_vector_type_get_element_type (C function) 6067 @anchor{topics/types c gcc_jit_vector_type_get_element_type}@anchor{a4} 6068 @deffn {C Function} gcc_jit_type * gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *@w{ }vector_type) 6069 6070 Given a vector type, return the type of its elements. 6071 @end deffn 6072 6073 @geindex gcc_jit_type_unqualified (C function) 6074 @anchor{topics/types c gcc_jit_type_unqualified}@anchor{a5} 6075 @deffn {C Function} gcc_jit_type * gcc_jit_type_unqualified (gcc_jit_type@w{ }*type) 6076 6077 Given a type, return the unqualified type, removing const, volatile and 6078 alignment qualifiers. 6079 @end deffn 6080 6081 @geindex gcc_jit_struct_get_field (C function) 6082 @anchor{topics/types c gcc_jit_struct_get_field}@anchor{a6} 6083 @deffn {C Function} gcc_jit_field * gcc_jit_struct_get_field (gcc_jit_struct@w{ }*struct_type, size_t@w{ }index) 6084 6085 Get a struct field by index. 6086 @end deffn 6087 6088 @geindex gcc_jit_struct_get_field_count (C function) 6089 @anchor{topics/types c gcc_jit_struct_get_field_count}@anchor{a7} 6090 @deffn {C Function} size_t gcc_jit_struct_get_field_count (gcc_jit_struct@w{ }*struct_type) 6091 6092 @quotation 6093 6094 Get the number of fields in the struct. 6095 @end quotation 6096 6097 The API entrypoints related to the reflection API: 6098 6099 @quotation 6100 6101 6102 @itemize * 6103 6104 @item 6105 @ref{9c,,gcc_jit_function_type_get_return_type()} 6106 6107 @item 6108 @ref{9d,,gcc_jit_function_type_get_param_count()} 6109 6110 @item 6111 @ref{9e,,gcc_jit_function_type_get_param_type()} 6112 6113 @item 6114 @ref{a5,,gcc_jit_type_unqualified()} 6115 6116 @item 6117 @ref{99,,gcc_jit_type_dyncast_array()} 6118 6119 @item 6120 @ref{9a,,gcc_jit_type_is_bool()} 6121 6122 @item 6123 @ref{9b,,gcc_jit_type_dyncast_function_ptr_type()} 6124 6125 @item 6126 @ref{9f,,gcc_jit_type_is_integral()} 6127 6128 @item 6129 @ref{a0,,gcc_jit_type_is_pointer()} 6130 6131 @item 6132 @ref{a1,,gcc_jit_type_dyncast_vector()} 6133 6134 @item 6135 @ref{a4,,gcc_jit_vector_type_get_element_type()} 6136 6137 @item 6138 @ref{a3,,gcc_jit_vector_type_get_num_units()} 6139 6140 @item 6141 @ref{a6,,gcc_jit_struct_get_field()} 6142 6143 @item 6144 @ref{a2,,gcc_jit_type_is_struct()} 6145 6146 @item 6147 @ref{a7,,gcc_jit_struct_get_field_count()} 6148 @end itemize 6149 @end quotation 6150 6151 were added in @ref{a8,,LIBGCCJIT_ABI_16}; you can test for their presence 6152 using 6153 6154 @example 6155 #ifdef LIBGCCJIT_HAVE_REFLECTION 6156 @end example 6157 6158 @geindex gcc_jit_case (C type) 6159 @anchor{topics/types c gcc_jit_case}@anchor{a9} 6160 @deffn {C Type} gcc_jit_case 6161 @end deffn 6162 @end deffn 6163 6164 @geindex gcc_jit_compatible_types (C function) 6165 @anchor{topics/types c gcc_jit_compatible_types}@anchor{aa} 6166 @deffn {C Function} int gcc_jit_compatible_types (gcc_jit_type@w{ }*ltype, gcc_jit_type@w{ }*rtype) 6167 6168 @quotation 6169 6170 Return non-zero if the two types are compatible. For instance, 6171 if @code{GCC_JIT_TYPE_UINT64_T} and @code{GCC_JIT_TYPE_UNSIGNED_LONG} 6172 are the same size on the target, this will return non-zero. 6173 The parameters @code{ltype} and @code{rtype} must be non-NULL. 6174 Return 0 on errors. 6175 @end quotation 6176 6177 This entrypoint was added in @ref{ab,,LIBGCCJIT_ABI_20}; you can test for 6178 its presence using 6179 6180 @example 6181 #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS 6182 @end example 6183 @end deffn 6184 6185 @geindex gcc_jit_type_get_size (C function) 6186 @anchor{topics/types c gcc_jit_type_get_size}@anchor{ac} 6187 @deffn {C Function} ssize_t gcc_jit_type_get_size (gcc_jit_type@w{ }*type) 6188 6189 @quotation 6190 6191 Return the size of a type, in bytes. It only works on integer types for now. 6192 The parameter @code{type} must be non-NULL. 6193 Return -1 on errors. 6194 @end quotation 6195 6196 This entrypoint was added in @ref{ab,,LIBGCCJIT_ABI_20}; you can test for 6197 its presence using 6198 6199 @example 6200 #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS 6201 @end example 6202 @end deffn 6203 6204 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 6205 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 6206 @c 6207 @c This is free software: you can redistribute it and/or modify it 6208 @c under the terms of the GNU General Public License as published by 6209 @c the Free Software Foundation, either version 3 of the License, or 6210 @c (at your option) any later version. 6211 @c 6212 @c This program is distributed in the hope that it will be useful, but 6213 @c WITHOUT ANY WARRANTY; without even the implied warranty of 6214 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 6215 @c General Public License for more details. 6216 @c 6217 @c You should have received a copy of the GNU General Public License 6218 @c along with this program. If not, see 6219 @c <https://www.gnu.org/licenses/>. 6220 6221 @node Expressions,Creating and using functions,Types,Topic Reference 6222 @anchor{topics/expressions doc}@anchor{ad}@anchor{topics/expressions expressions}@anchor{ae} 6223 @section Expressions 6224 6225 6226 @menu 6227 * Rvalues:: 6228 * Lvalues:: 6229 * Working with pointers@comma{} structs and unions: Working with pointers structs and unions. 6230 6231 @end menu 6232 6233 @node Rvalues,Lvalues,,Expressions 6234 @anchor{topics/expressions rvalues}@anchor{af} 6235 @subsection Rvalues 6236 6237 6238 @geindex gcc_jit_rvalue (C type) 6239 @anchor{topics/expressions c gcc_jit_rvalue}@anchor{13} 6240 @deffn {C Type} gcc_jit_rvalue 6241 @end deffn 6242 6243 A @ref{13,,gcc_jit_rvalue} is an expression that can be computed. 6244 6245 It can be simple, e.g.: 6246 6247 @quotation 6248 6249 6250 @itemize * 6251 6252 @item 6253 an integer value e.g. @cite{0} or @cite{42} 6254 6255 @item 6256 a string literal e.g. @cite{Hello world} 6257 6258 @item 6259 a variable e.g. @cite{i}. These are also lvalues (see below). 6260 @end itemize 6261 @end quotation 6262 6263 or compound e.g.: 6264 6265 @quotation 6266 6267 6268 @itemize * 6269 6270 @item 6271 a unary expression e.g. @cite{!cond} 6272 6273 @item 6274 a binary expression e.g. @cite{(a + b)} 6275 6276 @item 6277 a function call e.g. @cite{get_distance (&player_ship@comma{} &target)} 6278 6279 @item 6280 etc. 6281 @end itemize 6282 @end quotation 6283 6284 Every rvalue has an associated type, and the API will check to ensure 6285 that types match up correctly (otherwise the context will emit an error). 6286 6287 @geindex gcc_jit_rvalue_get_type (C function) 6288 @anchor{topics/expressions c gcc_jit_rvalue_get_type}@anchor{b0} 6289 @deffn {C Function} gcc_jit_type *gcc_jit_rvalue_get_type (gcc_jit_rvalue@w{ }*rvalue) 6290 6291 Get the type of this rvalue. 6292 @end deffn 6293 6294 @geindex gcc_jit_rvalue_as_object (C function) 6295 @anchor{topics/expressions c gcc_jit_rvalue_as_object}@anchor{14} 6296 @deffn {C Function} gcc_jit_object *gcc_jit_rvalue_as_object (gcc_jit_rvalue@w{ }*rvalue) 6297 6298 Upcast the given rvalue to be an object. 6299 @end deffn 6300 6301 @menu 6302 * Simple expressions:: 6303 * Constructor expressions:: 6304 * Vector expressions:: 6305 * Unary Operations:: 6306 * Binary Operations:: 6307 * Comparisons:: 6308 * Function calls:: 6309 * Function pointers:: 6310 * Type-coercion:: 6311 6312 @end menu 6313 6314 @node Simple expressions,Constructor expressions,,Rvalues 6315 @anchor{topics/expressions simple-expressions}@anchor{b1} 6316 @subsubsection Simple expressions 6317 6318 6319 @geindex gcc_jit_context_new_rvalue_from_int (C function) 6320 @anchor{topics/expressions c gcc_jit_context_new_rvalue_from_int}@anchor{30} 6321 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_int (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type, int@w{ }value) 6322 6323 Given a numeric type (integer or floating point), build an rvalue for 6324 the given constant @code{int} value. 6325 @end deffn 6326 6327 @geindex gcc_jit_context_new_rvalue_from_long (C function) 6328 @anchor{topics/expressions c gcc_jit_context_new_rvalue_from_long}@anchor{b2} 6329 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_long (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type, long@w{ }value) 6330 6331 Given a numeric type (integer or floating point), build an rvalue for 6332 the given constant @code{long} value. 6333 @end deffn 6334 6335 @geindex gcc_jit_context_zero (C function) 6336 @anchor{topics/expressions c gcc_jit_context_zero}@anchor{2b} 6337 @deffn {C Function} gcc_jit_rvalue *gcc_jit_context_zero (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type) 6338 6339 Given a numeric type (integer or floating point), get the rvalue for 6340 zero. Essentially this is just a shortcut for: 6341 6342 @example 6343 gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0) 6344 @end example 6345 @end deffn 6346 6347 @geindex gcc_jit_context_one (C function) 6348 @anchor{topics/expressions c gcc_jit_context_one}@anchor{2f} 6349 @deffn {C Function} gcc_jit_rvalue *gcc_jit_context_one (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type) 6350 6351 Given a numeric type (integer or floating point), get the rvalue for 6352 one. Essentially this is just a shortcut for: 6353 6354 @example 6355 gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1) 6356 @end example 6357 @end deffn 6358 6359 @geindex gcc_jit_context_new_rvalue_from_double (C function) 6360 @anchor{topics/expressions c gcc_jit_context_new_rvalue_from_double}@anchor{31} 6361 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_double (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type, double@w{ }value) 6362 6363 Given a numeric type (integer or floating point), build an rvalue for 6364 the given constant @code{double} value. 6365 @end deffn 6366 6367 @geindex gcc_jit_context_new_rvalue_from_ptr (C function) 6368 @anchor{topics/expressions c gcc_jit_context_new_rvalue_from_ptr}@anchor{b3} 6369 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type, void@w{ }*value) 6370 6371 Given a pointer type, build an rvalue for the given address. 6372 @end deffn 6373 6374 @geindex gcc_jit_context_null (C function) 6375 @anchor{topics/expressions c gcc_jit_context_null}@anchor{b4} 6376 @deffn {C Function} gcc_jit_rvalue *gcc_jit_context_null (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type) 6377 6378 Given a pointer type, build an rvalue for @code{NULL}. Essentially this 6379 is just a shortcut for: 6380 6381 @example 6382 gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL) 6383 @end example 6384 @end deffn 6385 6386 @geindex gcc_jit_context_new_string_literal (C function) 6387 @anchor{topics/expressions c gcc_jit_context_new_string_literal}@anchor{b5} 6388 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context@w{ }*ctxt, const char@w{ }*value) 6389 6390 Generate an rvalue for the given NIL-terminated string, of type 6391 @code{GCC_JIT_TYPE_CONST_CHAR_PTR}. 6392 6393 The parameter @code{value} must be non-NULL. The call takes a copy of the 6394 underlying string, so it is valid to pass in a pointer to an on-stack 6395 buffer. 6396 @end deffn 6397 6398 @node Constructor expressions,Vector expressions,Simple expressions,Rvalues 6399 @anchor{topics/expressions constructor-expressions}@anchor{b6} 6400 @subsubsection Constructor expressions 6401 6402 6403 @quotation 6404 6405 The following functions make constructors for array, struct and union 6406 types. 6407 6408 The constructor rvalue can be used for assignment to locals. 6409 It can be used to initialize global variables with 6410 @ref{b7,,gcc_jit_global_set_initializer_rvalue()}. It can also be used as a 6411 temporary value for function calls and return values, but its address 6412 cant be taken. 6413 6414 Note that arrays in libgccjit do not collapse to pointers like in 6415 C. I.e. if an array constructor is used as e.g. a return value, the whole 6416 array would be returned by value - array constructors can be assigned to 6417 array variables. 6418 6419 The constructor can contain nested constructors. 6420 6421 Note that a string literal rvalue cant be used to construct a char array; 6422 the latter needs one rvalue for each char. 6423 6424 These entrypoints were added in @ref{b8,,LIBGCCJIT_ABI_19}; you can test for 6425 their presence using: 6426 6427 @example 6428 #ifdef LIBGCCJIT_HAVE_CTORS 6429 @end example 6430 @end quotation 6431 6432 @geindex gcc_jit_context_new_array_constructor (C function) 6433 @anchor{topics/expressions c gcc_jit_context_new_array_constructor}@anchor{b9} 6434 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_array_constructor (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, size_t@w{ }num_values, gcc_jit_rvalue@w{ }**values) 6435 6436 Create a constructor for an array as an rvalue. 6437 6438 Returns NULL on error. @code{values} are copied and 6439 do not have to outlive the context. 6440 6441 @code{type} specifies what the constructor will build and has to be 6442 an array. 6443 6444 @code{num_values} specifies the number of elements in @code{values} and 6445 it cant have more elements than the array type. 6446 6447 Each value in @code{values} sets the corresponding value in the array. 6448 If the array type itself has more elements than @code{values}, the 6449 left-over elements will be zeroed. 6450 6451 Each value in @code{values} need to be the same unqualified type as the 6452 array types element type. 6453 6454 If @code{num_values} is 0, the @code{values} parameter will be 6455 ignored and zero initialization will be used. 6456 6457 This entrypoint was added in @ref{b8,,LIBGCCJIT_ABI_19}; you can test for its 6458 presence using: 6459 6460 @example 6461 #ifdef LIBGCCJIT_HAVE_CTORS 6462 @end example 6463 @end deffn 6464 6465 @geindex gcc_jit_context_new_struct_constructor (C function) 6466 @anchor{topics/expressions c gcc_jit_context_new_struct_constructor}@anchor{ba} 6467 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_struct_constructor (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, size_t@w{ }num_values, gcc_jit_field@w{ }**fields, gcc_jit_rvalue@w{ }**values) 6468 6469 Create a constructor for a struct as an rvalue. 6470 6471 Returns NULL on error. The two parameter arrays are copied and 6472 do not have to outlive the context. 6473 6474 @code{type} specifies what the constructor will build and has to be 6475 a struct. 6476 6477 @code{num_values} specifies the number of elements in @code{values}. 6478 6479 @code{fields} need to have the same length as @code{values}, or be NULL. 6480 6481 If @code{fields} is null, the values are applied in definition order. 6482 6483 Otherwise, each field in @code{fields} specifies which field in the struct to 6484 set to the corresponding value in @code{values}. @code{fields} and @code{values} 6485 are paired by index. 6486 6487 The fields in @code{fields} have to be in definition order, but there 6488 can be gaps. Any field in the struct that is not specified in 6489 @code{fields} will be zeroed. 6490 6491 The fields in @code{fields} need to be the same objects that were used 6492 to create the struct. 6493 6494 Each value has to have have the same unqualified type as the field 6495 it is applied to. 6496 6497 A NULL value element in @code{values} is a shorthand for zero initialization 6498 of the corresponding field. 6499 6500 If @code{num_values} is 0, the array parameters will be 6501 ignored and zero initialization will be used. 6502 6503 This entrypoint was added in @ref{b8,,LIBGCCJIT_ABI_19}; you can test for its 6504 presence using: 6505 6506 @example 6507 #ifdef LIBGCCJIT_HAVE_CTORS 6508 @end example 6509 @end deffn 6510 6511 @geindex gcc_jit_context_new_union_constructor (C function) 6512 @anchor{topics/expressions c gcc_jit_context_new_union_constructor}@anchor{bb} 6513 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_union_constructor (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, gcc_jit_field@w{ }*field, gcc_jit_rvalue@w{ }*value) 6514 6515 Create a constructor for a union as an rvalue. 6516 6517 Returns NULL on error. 6518 6519 @code{type} specifies what the constructor will build and has to be 6520 an union. 6521 6522 @code{field} specifies which field to set. If it is NULL, the first 6523 field in the union will be set.`@w{`}field`@w{`} need to be the same object 6524 that were used to create the union. 6525 6526 @code{value} specifies what value to set the corresponding field to. 6527 If @code{value} is NULL, zero initialization will be used. 6528 6529 Each value has to have have the same unqualified type as the field 6530 it is applied to. 6531 6532 This entrypoint was added in @ref{b8,,LIBGCCJIT_ABI_19}; you can test for its 6533 presence using: 6534 6535 @example 6536 #ifdef LIBGCCJIT_HAVE_CTORS 6537 @end example 6538 @end deffn 6539 6540 @node Vector expressions,Unary Operations,Constructor expressions,Rvalues 6541 @anchor{topics/expressions vector-expressions}@anchor{bc} 6542 @subsubsection Vector expressions 6543 6544 6545 @geindex gcc_jit_context_new_rvalue_from_vector (C function) 6546 @anchor{topics/expressions c gcc_jit_context_new_rvalue_from_vector}@anchor{89} 6547 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_vector (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*vec_type, size_t@w{ }num_elements, gcc_jit_rvalue@w{ }**elements) 6548 6549 Build a vector rvalue from an array of elements. 6550 6551 vec_type should be a vector type, created using 6552 @ref{87,,gcc_jit_type_get_vector()}. 6553 6554 num_elements should match that of the vector type. 6555 6556 This entrypoint was added in @ref{bd,,LIBGCCJIT_ABI_10}; you can test for 6557 its presence using 6558 6559 @example 6560 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector 6561 @end example 6562 @end deffn 6563 6564 @node Unary Operations,Binary Operations,Vector expressions,Rvalues 6565 @anchor{topics/expressions unary-operations}@anchor{be} 6566 @subsubsection Unary Operations 6567 6568 6569 @geindex gcc_jit_context_new_unary_op (C function) 6570 @anchor{topics/expressions c gcc_jit_context_new_unary_op}@anchor{bf} 6571 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_unary_op (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_unary_op@w{ }op, gcc_jit_type@w{ }*result_type, gcc_jit_rvalue@w{ }*rvalue) 6572 6573 Build a unary operation out of an input rvalue. 6574 6575 The parameter @code{result_type} must be a numeric type. 6576 @end deffn 6577 6578 @geindex gcc_jit_unary_op (C type) 6579 @anchor{topics/expressions c gcc_jit_unary_op}@anchor{c0} 6580 @deffn {C Type} enum gcc_jit_unary_op 6581 @end deffn 6582 6583 The available unary operations are: 6584 6585 6586 @multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6587 @headitem 6588 6589 Unary Operation 6590 6591 @tab 6592 6593 C equivalent 6594 6595 @item 6596 6597 @ref{c1,,GCC_JIT_UNARY_OP_MINUS} 6598 6599 @tab 6600 6601 @cite{-(EXPR)} 6602 6603 @item 6604 6605 @ref{c2,,GCC_JIT_UNARY_OP_BITWISE_NEGATE} 6606 6607 @tab 6608 6609 @cite{~(EXPR)} 6610 6611 @item 6612 6613 @ref{c3,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE} 6614 6615 @tab 6616 6617 @cite{!(EXPR)} 6618 6619 @item 6620 6621 @ref{c4,,GCC_JIT_UNARY_OP_ABS} 6622 6623 @tab 6624 6625 @cite{abs (EXPR)} 6626 6627 @end multitable 6628 6629 6630 @geindex GCC_JIT_UNARY_OP_MINUS (C macro) 6631 @anchor{topics/expressions c GCC_JIT_UNARY_OP_MINUS}@anchor{c1} 6632 @deffn {C Macro} GCC_JIT_UNARY_OP_MINUS 6633 6634 Negate an arithmetic value; analogous to: 6635 6636 @example 6637 -(EXPR) 6638 @end example 6639 6640 in C. 6641 @end deffn 6642 6643 @geindex GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro) 6644 @anchor{topics/expressions c GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{c2} 6645 @deffn {C Macro} GCC_JIT_UNARY_OP_BITWISE_NEGATE 6646 6647 Bitwise negation of an integer value (ones complement); analogous 6648 to: 6649 6650 @example 6651 ~(EXPR) 6652 @end example 6653 6654 in C. 6655 @end deffn 6656 6657 @geindex GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro) 6658 @anchor{topics/expressions c GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{c3} 6659 @deffn {C Macro} GCC_JIT_UNARY_OP_LOGICAL_NEGATE 6660 6661 Logical negation of an arithmetic or pointer value; analogous to: 6662 6663 @example 6664 !(EXPR) 6665 @end example 6666 6667 in C. 6668 @end deffn 6669 6670 @geindex GCC_JIT_UNARY_OP_ABS (C macro) 6671 @anchor{topics/expressions c GCC_JIT_UNARY_OP_ABS}@anchor{c4} 6672 @deffn {C Macro} GCC_JIT_UNARY_OP_ABS 6673 6674 Absolute value of an arithmetic expression; analogous to: 6675 6676 @example 6677 abs (EXPR) 6678 @end example 6679 6680 in C. 6681 @end deffn 6682 6683 @node Binary Operations,Comparisons,Unary Operations,Rvalues 6684 @anchor{topics/expressions binary-operations}@anchor{c5} 6685 @subsubsection Binary Operations 6686 6687 6688 @geindex gcc_jit_context_new_binary_op (C function) 6689 @anchor{topics/expressions c gcc_jit_context_new_binary_op}@anchor{12} 6690 @deffn {C Function} gcc_jit_rvalue *gcc_jit_context_new_binary_op (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_binary_op@w{ }op, gcc_jit_type@w{ }*result_type, gcc_jit_rvalue@w{ }*a, gcc_jit_rvalue@w{ }*b) 6691 6692 Build a binary operation out of two constituent rvalues. 6693 6694 The parameter @code{result_type} must be a numeric type. 6695 @end deffn 6696 6697 @geindex gcc_jit_binary_op (C type) 6698 @anchor{topics/expressions c gcc_jit_binary_op}@anchor{c6} 6699 @deffn {C Type} enum gcc_jit_binary_op 6700 @end deffn 6701 6702 The available binary operations are: 6703 6704 6705 @multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6706 @headitem 6707 6708 Binary Operation 6709 6710 @tab 6711 6712 C equivalent 6713 6714 @item 6715 6716 @ref{c7,,GCC_JIT_BINARY_OP_PLUS} 6717 6718 @tab 6719 6720 @cite{x + y} 6721 6722 @item 6723 6724 @ref{c8,,GCC_JIT_BINARY_OP_MINUS} 6725 6726 @tab 6727 6728 @cite{x - y} 6729 6730 @item 6731 6732 @ref{c9,,GCC_JIT_BINARY_OP_MULT} 6733 6734 @tab 6735 6736 @cite{x * y} 6737 6738 @item 6739 6740 @ref{ca,,GCC_JIT_BINARY_OP_DIVIDE} 6741 6742 @tab 6743 6744 @cite{x / y} 6745 6746 @item 6747 6748 @ref{cb,,GCC_JIT_BINARY_OP_MODULO} 6749 6750 @tab 6751 6752 @cite{x % y} 6753 6754 @item 6755 6756 @ref{cc,,GCC_JIT_BINARY_OP_BITWISE_AND} 6757 6758 @tab 6759 6760 @cite{x & y} 6761 6762 @item 6763 6764 @ref{cd,,GCC_JIT_BINARY_OP_BITWISE_XOR} 6765 6766 @tab 6767 6768 @cite{x ^ y} 6769 6770 @item 6771 6772 @ref{ce,,GCC_JIT_BINARY_OP_BITWISE_OR} 6773 6774 @tab 6775 6776 @cite{x | y} 6777 6778 @item 6779 6780 @ref{cf,,GCC_JIT_BINARY_OP_LOGICAL_AND} 6781 6782 @tab 6783 6784 @cite{x && y} 6785 6786 @item 6787 6788 @ref{d0,,GCC_JIT_BINARY_OP_LOGICAL_OR} 6789 6790 @tab 6791 6792 @cite{x || y} 6793 6794 @item 6795 6796 @ref{d1,,GCC_JIT_BINARY_OP_LSHIFT} 6797 6798 @tab 6799 6800 @cite{x << y} 6801 6802 @item 6803 6804 @ref{d2,,GCC_JIT_BINARY_OP_RSHIFT} 6805 6806 @tab 6807 6808 @cite{x >> y} 6809 6810 @end multitable 6811 6812 6813 @geindex GCC_JIT_BINARY_OP_PLUS (C macro) 6814 @anchor{topics/expressions c GCC_JIT_BINARY_OP_PLUS}@anchor{c7} 6815 @deffn {C Macro} GCC_JIT_BINARY_OP_PLUS 6816 6817 Addition of arithmetic values; analogous to: 6818 6819 @example 6820 (EXPR_A) + (EXPR_B) 6821 @end example 6822 6823 in C. 6824 6825 For pointer addition, use @ref{d3,,gcc_jit_context_new_array_access()}. 6826 @end deffn 6827 6828 @geindex GCC_JIT_BINARY_OP_MINUS (C macro) 6829 @anchor{topics/expressions c GCC_JIT_BINARY_OP_MINUS}@anchor{c8} 6830 @deffn {C Macro} GCC_JIT_BINARY_OP_MINUS 6831 6832 Subtraction of arithmetic values; analogous to: 6833 6834 @example 6835 (EXPR_A) - (EXPR_B) 6836 @end example 6837 6838 in C. 6839 @end deffn 6840 6841 @geindex GCC_JIT_BINARY_OP_MULT (C macro) 6842 @anchor{topics/expressions c GCC_JIT_BINARY_OP_MULT}@anchor{c9} 6843 @deffn {C Macro} GCC_JIT_BINARY_OP_MULT 6844 6845 Multiplication of a pair of arithmetic values; analogous to: 6846 6847 @example 6848 (EXPR_A) * (EXPR_B) 6849 @end example 6850 6851 in C. 6852 @end deffn 6853 6854 @geindex GCC_JIT_BINARY_OP_DIVIDE (C macro) 6855 @anchor{topics/expressions c GCC_JIT_BINARY_OP_DIVIDE}@anchor{ca} 6856 @deffn {C Macro} GCC_JIT_BINARY_OP_DIVIDE 6857 6858 Quotient of division of arithmetic values; analogous to: 6859 6860 @example 6861 (EXPR_A) / (EXPR_B) 6862 @end example 6863 6864 in C. 6865 6866 The result type affects the kind of division: if the result type is 6867 integer-based, then the result is truncated towards zero, whereas 6868 a floating-point result type indicates floating-point division. 6869 @end deffn 6870 6871 @geindex GCC_JIT_BINARY_OP_MODULO (C macro) 6872 @anchor{topics/expressions c GCC_JIT_BINARY_OP_MODULO}@anchor{cb} 6873 @deffn {C Macro} GCC_JIT_BINARY_OP_MODULO 6874 6875 Remainder of division of arithmetic values; analogous to: 6876 6877 @example 6878 (EXPR_A) % (EXPR_B) 6879 @end example 6880 6881 in C. 6882 @end deffn 6883 6884 @geindex GCC_JIT_BINARY_OP_BITWISE_AND (C macro) 6885 @anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{cc} 6886 @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_AND 6887 6888 Bitwise AND; analogous to: 6889 6890 @example 6891 (EXPR_A) & (EXPR_B) 6892 @end example 6893 6894 in C. 6895 @end deffn 6896 6897 @geindex GCC_JIT_BINARY_OP_BITWISE_XOR (C macro) 6898 @anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{cd} 6899 @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_XOR 6900 6901 Bitwise exclusive OR; analogous to: 6902 6903 @example 6904 (EXPR_A) ^ (EXPR_B) 6905 @end example 6906 6907 in C. 6908 @end deffn 6909 6910 @geindex GCC_JIT_BINARY_OP_BITWISE_OR (C macro) 6911 @anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{ce} 6912 @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_OR 6913 6914 Bitwise inclusive OR; analogous to: 6915 6916 @example 6917 (EXPR_A) | (EXPR_B) 6918 @end example 6919 6920 in C. 6921 @end deffn 6922 6923 @geindex GCC_JIT_BINARY_OP_LOGICAL_AND (C macro) 6924 @anchor{topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{cf} 6925 @deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_AND 6926 6927 Logical AND; analogous to: 6928 6929 @example 6930 (EXPR_A) && (EXPR_B) 6931 @end example 6932 6933 in C. 6934 @end deffn 6935 6936 @geindex GCC_JIT_BINARY_OP_LOGICAL_OR (C macro) 6937 @anchor{topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{d0} 6938 @deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_OR 6939 6940 Logical OR; analogous to: 6941 6942 @example 6943 (EXPR_A) || (EXPR_B) 6944 @end example 6945 6946 in C. 6947 @end deffn 6948 6949 @geindex GCC_JIT_BINARY_OP_LSHIFT (C macro) 6950 @anchor{topics/expressions c GCC_JIT_BINARY_OP_LSHIFT}@anchor{d1} 6951 @deffn {C Macro} GCC_JIT_BINARY_OP_LSHIFT 6952 6953 Left shift; analogous to: 6954 6955 @example 6956 (EXPR_A) << (EXPR_B) 6957 @end example 6958 6959 in C. 6960 @end deffn 6961 6962 @geindex GCC_JIT_BINARY_OP_RSHIFT (C macro) 6963 @anchor{topics/expressions c GCC_JIT_BINARY_OP_RSHIFT}@anchor{d2} 6964 @deffn {C Macro} GCC_JIT_BINARY_OP_RSHIFT 6965 6966 Right shift; analogous to: 6967 6968 @example 6969 (EXPR_A) >> (EXPR_B) 6970 @end example 6971 6972 in C. 6973 @end deffn 6974 6975 @node Comparisons,Function calls,Binary Operations,Rvalues 6976 @anchor{topics/expressions comparisons}@anchor{d4} 6977 @subsubsection Comparisons 6978 6979 6980 @geindex gcc_jit_context_new_comparison (C function) 6981 @anchor{topics/expressions c gcc_jit_context_new_comparison}@anchor{2c} 6982 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_comparison (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_comparison@w{ }op, gcc_jit_rvalue@w{ }*a, gcc_jit_rvalue@w{ }*b) 6983 6984 Build a boolean rvalue out of the comparison of two other rvalues. 6985 @end deffn 6986 6987 @geindex gcc_jit_comparison (C type) 6988 @anchor{topics/expressions c gcc_jit_comparison}@anchor{d5} 6989 @deffn {C Type} enum gcc_jit_comparison 6990 @end deffn 6991 6992 6993 @multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6994 @headitem 6995 6996 Comparison 6997 6998 @tab 6999 7000 C equivalent 7001 7002 @item 7003 7004 @code{GCC_JIT_COMPARISON_EQ} 7005 7006 @tab 7007 7008 @cite{x == y} 7009 7010 @item 7011 7012 @code{GCC_JIT_COMPARISON_NE} 7013 7014 @tab 7015 7016 @cite{x != y} 7017 7018 @item 7019 7020 @code{GCC_JIT_COMPARISON_LT} 7021 7022 @tab 7023 7024 @cite{x < y} 7025 7026 @item 7027 7028 @code{GCC_JIT_COMPARISON_LE} 7029 7030 @tab 7031 7032 @cite{x <= y} 7033 7034 @item 7035 7036 @code{GCC_JIT_COMPARISON_GT} 7037 7038 @tab 7039 7040 @cite{x > y} 7041 7042 @item 7043 7044 @code{GCC_JIT_COMPARISON_GE} 7045 7046 @tab 7047 7048 @cite{x >= y} 7049 7050 @end multitable 7051 7052 7053 @node Function calls,Function pointers,Comparisons,Rvalues 7054 @anchor{topics/expressions function-calls}@anchor{d6} 7055 @subsubsection Function calls 7056 7057 7058 @geindex gcc_jit_context_new_call (C function) 7059 @anchor{topics/expressions c gcc_jit_context_new_call}@anchor{d7} 7060 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_call (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_function@w{ }*func, int@w{ }numargs, gcc_jit_rvalue@w{ }**args) 7061 7062 Given a function and the given table of argument rvalues, construct a 7063 call to the function, with the result as an rvalue. 7064 7065 @cartouche 7066 @quotation Note 7067 @ref{d7,,gcc_jit_context_new_call()} merely builds a 7068 @ref{13,,gcc_jit_rvalue} i.e. an expression that can be evaluated, 7069 perhaps as part of a more complicated expression. 7070 The call @emph{wont} happen unless you add a statement to a function 7071 that evaluates the expression. 7072 7073 For example, if you want to call a function and discard the result 7074 (or to call a function with @code{void} return type), use 7075 @ref{d8,,gcc_jit_block_add_eval()}: 7076 7077 @example 7078 /* Add "(void)printf (arg0, arg1);". */ 7079 gcc_jit_block_add_eval ( 7080 block, NULL, 7081 gcc_jit_context_new_call ( 7082 ctxt, 7083 NULL, 7084 printf_func, 7085 2, args)); 7086 @end example 7087 @end quotation 7088 @end cartouche 7089 @end deffn 7090 7091 @geindex gcc_jit_context_new_call_through_ptr (C function) 7092 @anchor{topics/expressions c gcc_jit_context_new_call_through_ptr}@anchor{d9} 7093 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_call_through_ptr (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*fn_ptr, int@w{ }numargs, gcc_jit_rvalue@w{ }**args) 7094 7095 Given an rvalue of function pointer type (e.g. from 7096 @ref{97,,gcc_jit_context_new_function_ptr_type()}), and the given table of 7097 argument rvalues, construct a call to the function pointer, with the 7098 result as an rvalue. 7099 7100 @cartouche 7101 @quotation Note 7102 The same caveat as for @ref{d7,,gcc_jit_context_new_call()} applies. 7103 @end quotation 7104 @end cartouche 7105 @end deffn 7106 7107 @geindex gcc_jit_rvalue_set_bool_require_tail_call (C function) 7108 @anchor{topics/expressions c gcc_jit_rvalue_set_bool_require_tail_call}@anchor{da} 7109 @deffn {C Function} void gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue@w{ }*call, int@w{ }require_tail_call) 7110 7111 Given an @ref{13,,gcc_jit_rvalue} for a call created through 7112 @ref{d7,,gcc_jit_context_new_call()} or 7113 @ref{d9,,gcc_jit_context_new_call_through_ptr()}, mark/clear the 7114 call as needing tail-call optimization. The optimizer will 7115 attempt to optimize the call into a jump instruction; if it is 7116 unable to do do, an error will be emitted. 7117 7118 This may be useful when implementing functions that use the 7119 continuation-passing style (e.g. for functional programming 7120 languages), in which every function returns by calling a 7121 continuation function pointer. This call must be 7122 guaranteed to be implemented as a jump, otherwise the program 7123 could consume an arbitrary amount of stack space as it executed. 7124 7125 This entrypoint was added in @ref{db,,LIBGCCJIT_ABI_6}; you can test for 7126 its presence using 7127 7128 @example 7129 #ifdef LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call 7130 @end example 7131 @end deffn 7132 7133 @node Function pointers,Type-coercion,Function calls,Rvalues 7134 @anchor{topics/expressions function-pointers}@anchor{dc} 7135 @subsubsection Function pointers 7136 7137 7138 Function pointers can be obtained: 7139 7140 @quotation 7141 7142 7143 @itemize * 7144 7145 @item 7146 from a @ref{29,,gcc_jit_function} using 7147 @ref{dd,,gcc_jit_function_get_address()}, or 7148 7149 @item 7150 from an existing function using 7151 @ref{b3,,gcc_jit_context_new_rvalue_from_ptr()}, 7152 using a function pointer type obtained using 7153 @ref{97,,gcc_jit_context_new_function_ptr_type()}. 7154 @end itemize 7155 @end quotation 7156 7157 @node Type-coercion,,Function pointers,Rvalues 7158 @anchor{topics/expressions type-coercion}@anchor{de} 7159 @subsubsection Type-coercion 7160 7161 7162 @geindex gcc_jit_context_new_cast (C function) 7163 @anchor{topics/expressions c gcc_jit_context_new_cast}@anchor{df} 7164 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_cast (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue, gcc_jit_type@w{ }*type) 7165 7166 Given an rvalue of T, construct another rvalue of another type. 7167 7168 Currently only a limited set of conversions are possible: 7169 7170 @quotation 7171 7172 7173 @itemize * 7174 7175 @item 7176 int <-> float 7177 7178 @item 7179 int <-> bool 7180 7181 @item 7182 P* <-> Q*, for pointer types P and Q 7183 @end itemize 7184 @end quotation 7185 @end deffn 7186 7187 @geindex gcc_jit_context_new_bitcast (C function) 7188 @anchor{topics/expressions c gcc_jit_context_new_bitcast}@anchor{e0} 7189 @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_bitcast (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue, gcc_jit_type@w{ }*type) 7190 7191 Given an rvalue of T, bitcast it to another type, meaning that this will 7192 generate a new rvalue by interpreting the bits of @code{rvalue} to the layout 7193 of @code{type}. 7194 7195 The type of rvalue must be the same size as the size of @code{type}. 7196 7197 This entrypoint was added in @ref{e1,,LIBGCCJIT_ABI_21}; you can test for 7198 its presence using 7199 7200 @example 7201 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast 7202 @end example 7203 @end deffn 7204 7205 @node Lvalues,Working with pointers structs and unions,Rvalues,Expressions 7206 @anchor{topics/expressions lvalues}@anchor{e2} 7207 @subsection Lvalues 7208 7209 7210 @geindex gcc_jit_lvalue (C type) 7211 @anchor{topics/expressions c gcc_jit_lvalue}@anchor{24} 7212 @deffn {C Type} gcc_jit_lvalue 7213 @end deffn 7214 7215 An lvalue is something that can of the @emph{left}-hand side of an assignment: 7216 a storage area (such as a variable). It is also usable as an rvalue, 7217 where the rvalue is computed by reading from the storage area. 7218 7219 @geindex gcc_jit_lvalue_as_object (C function) 7220 @anchor{topics/expressions c gcc_jit_lvalue_as_object}@anchor{e3} 7221 @deffn {C Function} gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue@w{ }*lvalue) 7222 7223 Upcast an lvalue to be an object. 7224 @end deffn 7225 7226 @geindex gcc_jit_lvalue_as_rvalue (C function) 7227 @anchor{topics/expressions c gcc_jit_lvalue_as_rvalue}@anchor{e4} 7228 @deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue@w{ }*lvalue) 7229 7230 Upcast an lvalue to be an rvalue. 7231 @end deffn 7232 7233 @geindex gcc_jit_lvalue_get_address (C function) 7234 @anchor{topics/expressions c gcc_jit_lvalue_get_address}@anchor{e5} 7235 @deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_get_address (gcc_jit_lvalue@w{ }*lvalue, gcc_jit_location@w{ }*loc) 7236 7237 Take the address of an lvalue; analogous to: 7238 7239 @example 7240 &(EXPR) 7241 @end example 7242 7243 in C. 7244 @end deffn 7245 7246 @geindex gcc_jit_lvalue_set_tls_model (C function) 7247 @anchor{topics/expressions c gcc_jit_lvalue_set_tls_model}@anchor{e6} 7248 @deffn {C Function} void gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue@w{ }*lvalue, enum gcc_jit_tls_model@w{ }model) 7249 7250 Make a variable a thread-local variable. 7251 7252 The model parameter determines the thread-local storage model of the lvalue: 7253 7254 @geindex gcc_jit_tls_model (C type) 7255 @anchor{topics/expressions c gcc_jit_tls_model}@anchor{e7} 7256 @deffn {C Type} enum gcc_jit_tls_model 7257 @end deffn 7258 7259 @geindex GCC_JIT_TLS_MODEL_NONE (C macro) 7260 @anchor{topics/expressions c GCC_JIT_TLS_MODEL_NONE}@anchor{e8} 7261 @deffn {C Macro} GCC_JIT_TLS_MODEL_NONE 7262 7263 Dont set the TLS model. 7264 @end deffn 7265 7266 @geindex GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC (C macro) 7267 @anchor{topics/expressions c GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC}@anchor{e9} 7268 @deffn {C Macro} GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC 7269 @end deffn 7270 7271 @geindex GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC (C macro) 7272 @anchor{topics/expressions c GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC}@anchor{ea} 7273 @deffn {C Macro} GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC 7274 @end deffn 7275 7276 @geindex GCC_JIT_TLS_MODEL_INITIAL_EXEC (C macro) 7277 @anchor{topics/expressions c GCC_JIT_TLS_MODEL_INITIAL_EXEC}@anchor{eb} 7278 @deffn {C Macro} GCC_JIT_TLS_MODEL_INITIAL_EXEC 7279 @end deffn 7280 7281 @geindex GCC_JIT_TLS_MODEL_LOCAL_EXEC (C macro) 7282 @anchor{topics/expressions c GCC_JIT_TLS_MODEL_LOCAL_EXEC}@anchor{ec} 7283 @deffn {C Macro} GCC_JIT_TLS_MODEL_LOCAL_EXEC 7284 @end deffn 7285 7286 This is analogous to: 7287 7288 @example 7289 _Thread_local int foo __attribute__ ((tls_model("MODEL"))); 7290 @end example 7291 7292 in C. 7293 7294 This entrypoint was added in @ref{ed,,LIBGCCJIT_ABI_17}; you can test for 7295 its presence using 7296 7297 @example 7298 #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model 7299 @end example 7300 @end deffn 7301 7302 @geindex gcc_jit_lvalue_set_link_section (C function) 7303 @anchor{topics/expressions c gcc_jit_lvalue_set_link_section}@anchor{ee} 7304 @deffn {C Function} void gcc_jit_lvalue_set_link_section (gcc_jit_lvalue@w{ }*lvalue, const char@w{ }*section_name) 7305 7306 Set the link section of a variable. 7307 The parameter @code{section_name} must be non-NULL and must contain the 7308 leading dot. Analogous to: 7309 7310 @example 7311 int variable __attribute__((section(".section"))); 7312 @end example 7313 7314 in C. 7315 7316 This entrypoint was added in @ref{ef,,LIBGCCJIT_ABI_18}; you can test for 7317 its presence using 7318 7319 @example 7320 #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_link_section 7321 @end example 7322 @end deffn 7323 7324 7325 @deffn {C Function} void gcc_jit_lvalue_set_register_name (gcc_jit_lvalue *lvalue, const char *reg_name); 7326 7327 Set the register name of a variable. 7328 The parameter @code{reg_name} must be non-NULL. Analogous to: 7329 7330 @example 7331 register int variable asm ("r12"); 7332 @end example 7333 7334 in C. 7335 7336 This entrypoint was added in @ref{f0,,LIBGCCJIT_ABI_22}; you can test for 7337 its presence using 7338 7339 @example 7340 #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_register_name 7341 @end example 7342 @end deffn 7343 7344 @geindex gcc_jit_lvalue_set_alignment (C function) 7345 @anchor{topics/expressions c gcc_jit_lvalue_set_alignment}@anchor{f1} 7346 @deffn {C Function} void gcc_jit_lvalue_set_alignment (gcc_jit_lvalue@w{ }*lvalue, unsigned@w{ }bytes) 7347 7348 Set the alignment of a variable, in bytes. 7349 Analogous to: 7350 7351 @example 7352 int variable __attribute__((aligned (16))); 7353 @end example 7354 7355 in C. 7356 7357 This entrypoint was added in @ref{f2,,LIBGCCJIT_ABI_24}; you can test for 7358 its presence using 7359 7360 @example 7361 #ifdef LIBGCCJIT_HAVE_ALIGNMENT 7362 @end example 7363 @end deffn 7364 7365 @geindex gcc_jit_lvalue_get_alignment (C function) 7366 @anchor{topics/expressions c gcc_jit_lvalue_get_alignment}@anchor{f3} 7367 @deffn {C Function} unsigned gcc_jit_lvalue_get_alignment (gcc_jit_lvalue@w{ }*lvalue) 7368 7369 Return the alignment of a variable set by @code{gcc_jit_lvalue_set_alignment}. 7370 Return 0 if the alignment was not set. Analogous to: 7371 7372 @example 7373 _Alignof (variable) 7374 @end example 7375 7376 in C. 7377 7378 This entrypoint was added in @ref{f2,,LIBGCCJIT_ABI_24}; you can test for 7379 its presence using 7380 7381 @example 7382 #ifdef LIBGCCJIT_HAVE_ALIGNMENT 7383 @end example 7384 @end deffn 7385 7386 @menu 7387 * Global variables:: 7388 7389 @end menu 7390 7391 @node Global variables,,,Lvalues 7392 @anchor{topics/expressions global-variables}@anchor{f4} 7393 @subsubsection Global variables 7394 7395 7396 @geindex gcc_jit_context_new_global (C function) 7397 @anchor{topics/expressions c gcc_jit_context_new_global}@anchor{f5} 7398 @deffn {C Function} gcc_jit_lvalue * gcc_jit_context_new_global (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_global_kind@w{ }kind, gcc_jit_type@w{ }*type, const char@w{ }*name) 7399 7400 Add a new global variable of the given type and name to the context. 7401 7402 The parameter @code{type} must be non-@cite{void}. 7403 7404 The parameter @code{name} must be non-NULL. The call takes a copy of the 7405 underlying string, so it is valid to pass in a pointer to an on-stack 7406 buffer. 7407 7408 The kind parameter determines the visibility of the global outside 7409 of the @ref{16,,gcc_jit_result}: 7410 7411 @geindex gcc_jit_global_kind (C type) 7412 @anchor{topics/expressions c gcc_jit_global_kind}@anchor{f6} 7413 @deffn {C Type} enum gcc_jit_global_kind 7414 @end deffn 7415 7416 @geindex GCC_JIT_GLOBAL_EXPORTED (C macro) 7417 @anchor{topics/expressions c GCC_JIT_GLOBAL_EXPORTED}@anchor{f7} 7418 @deffn {C Macro} GCC_JIT_GLOBAL_EXPORTED 7419 7420 Global is defined by the client code and is visible 7421 by name outside of this JIT context via 7422 @ref{f8,,gcc_jit_result_get_global()} (and this value is required for 7423 the global to be accessible via that entrypoint). 7424 @end deffn 7425 7426 @geindex GCC_JIT_GLOBAL_INTERNAL (C macro) 7427 @anchor{topics/expressions c GCC_JIT_GLOBAL_INTERNAL}@anchor{f9} 7428 @deffn {C Macro} GCC_JIT_GLOBAL_INTERNAL 7429 7430 Global is defined by the client code, but is invisible 7431 outside of it. Analogous to a static global within a .c file. 7432 Specifically, the variable will only be visible within this 7433 context and within child contexts. 7434 @end deffn 7435 7436 @geindex GCC_JIT_GLOBAL_IMPORTED (C macro) 7437 @anchor{topics/expressions c GCC_JIT_GLOBAL_IMPORTED}@anchor{fa} 7438 @deffn {C Macro} GCC_JIT_GLOBAL_IMPORTED 7439 7440 Global is not defined by the client code; were merely 7441 referring to it. Analogous to using an extern global from a 7442 header file. 7443 @end deffn 7444 @end deffn 7445 7446 @geindex gcc_jit_global_set_initializer (C function) 7447 @anchor{topics/expressions c gcc_jit_global_set_initializer}@anchor{fb} 7448 @deffn {C Function} gcc_jit_lvalue * gcc_jit_global_set_initializer (gcc_jit_lvalue@w{ }*global, const void@w{ }*blob, size_t@w{ }num_bytes) 7449 7450 Set an initializer for @code{global} using the memory content pointed 7451 by @code{blob} for @code{num_bytes}. @code{global} must be an array of an 7452 integral type. Return the global itself. 7453 7454 The parameter @code{blob} must be non-NULL. The call copies the memory 7455 pointed by @code{blob} for @code{num_bytes} bytes, so it is valid to pass 7456 in a pointer to an on-stack buffer. The content will be stored in 7457 the compilation unit and used as initialization value of the array. 7458 7459 This entrypoint was added in @ref{fc,,LIBGCCJIT_ABI_14}; you can test for 7460 its presence using 7461 7462 @example 7463 #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer 7464 @end example 7465 @end deffn 7466 7467 @geindex gcc_jit_global_set_initializer_rvalue (C function) 7468 @anchor{topics/expressions c gcc_jit_global_set_initializer_rvalue}@anchor{b7} 7469 @deffn {C Function} gcc_jit_lvalue * gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue@w{ }*global, gcc_jit_rvalue@w{ }*init_value) 7470 7471 Set the initial value of a global with an rvalue. 7472 7473 The rvalue needs to be a constant expression, e.g. no function calls. 7474 7475 The global cant have the @code{kind} @ref{fa,,GCC_JIT_GLOBAL_IMPORTED}. 7476 7477 As a non-comprehensive example it is OK to do the equivalent of: 7478 7479 @example 7480 int foo = 3 * 2; /* rvalue from gcc_jit_context_new_binary_op. */ 7481 int arr[] = @{1,2,3,4@}; /* rvalue from gcc_jit_context_new_constructor. */ 7482 int *bar = &arr[2] + 1; /* rvalue from nested "get address" of "array access". */ 7483 const int baz = 3; /* rvalue from gcc_jit_context_rvalue_from_int. */ 7484 int boz = baz; /* rvalue from gcc_jit_lvalue_as_rvalue. */ 7485 @end example 7486 7487 Use together with @ref{ba,,gcc_jit_context_new_struct_constructor()}, 7488 @ref{bb,,gcc_jit_context_new_union_constructor()}, @ref{b9,,gcc_jit_context_new_array_constructor()} 7489 to initialize structs, unions and arrays. 7490 7491 On success, returns the @code{global} parameter unchanged. Otherwise, @code{NULL}. 7492 7493 This entrypoint was added in @ref{b8,,LIBGCCJIT_ABI_19}; you can test for its 7494 presence using: 7495 7496 @example 7497 #ifdef LIBGCCJIT_HAVE_CTORS 7498 @end example 7499 @end deffn 7500 7501 @node Working with pointers structs and unions,,Lvalues,Expressions 7502 @anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{fd} 7503 @subsection Working with pointers, structs and unions 7504 7505 7506 @geindex gcc_jit_rvalue_dereference (C function) 7507 @anchor{topics/expressions c gcc_jit_rvalue_dereference}@anchor{fe} 7508 @deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference (gcc_jit_rvalue@w{ }*rvalue, gcc_jit_location@w{ }*loc) 7509 7510 Given an rvalue of pointer type @code{T *}, dereferencing the pointer, 7511 getting an lvalue of type @code{T}. Analogous to: 7512 7513 @example 7514 *(EXPR) 7515 @end example 7516 7517 in C. 7518 @end deffn 7519 7520 Field access is provided separately for both lvalues and rvalues. 7521 7522 @geindex gcc_jit_lvalue_access_field (C function) 7523 @anchor{topics/expressions c gcc_jit_lvalue_access_field}@anchor{ff} 7524 @deffn {C Function} gcc_jit_lvalue * gcc_jit_lvalue_access_field (gcc_jit_lvalue@w{ }*struct_, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field) 7525 7526 Given an lvalue of struct or union type, access the given field, 7527 getting an lvalue of the fields type. Analogous to: 7528 7529 @example 7530 (EXPR).field = ...; 7531 @end example 7532 7533 in C. 7534 @end deffn 7535 7536 @geindex gcc_jit_rvalue_access_field (C function) 7537 @anchor{topics/expressions c gcc_jit_rvalue_access_field}@anchor{100} 7538 @deffn {C Function} gcc_jit_rvalue * gcc_jit_rvalue_access_field (gcc_jit_rvalue@w{ }*struct_, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field) 7539 7540 Given an rvalue of struct or union type, access the given field 7541 as an rvalue. Analogous to: 7542 7543 @example 7544 (EXPR).field 7545 @end example 7546 7547 in C. 7548 @end deffn 7549 7550 @geindex gcc_jit_rvalue_dereference_field (C function) 7551 @anchor{topics/expressions c gcc_jit_rvalue_dereference_field}@anchor{101} 7552 @deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference_field (gcc_jit_rvalue@w{ }*ptr, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field) 7553 7554 Given an rvalue of pointer type @code{T *} where T is of struct or union 7555 type, access the given field as an lvalue. Analogous to: 7556 7557 @example 7558 (EXPR)->field 7559 @end example 7560 7561 in C, itself equivalent to @code{(*EXPR).FIELD}. 7562 @end deffn 7563 7564 @geindex gcc_jit_context_new_array_access (C function) 7565 @anchor{topics/expressions c gcc_jit_context_new_array_access}@anchor{d3} 7566 @deffn {C Function} gcc_jit_lvalue * gcc_jit_context_new_array_access (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*ptr, gcc_jit_rvalue@w{ }*index) 7567 7568 Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at 7569 the given index, using standard C array indexing rules i.e. each 7570 increment of @code{index} corresponds to @code{sizeof(T)} bytes. 7571 Analogous to: 7572 7573 @example 7574 PTR[INDEX] 7575 @end example 7576 7577 in C (or, indeed, to @code{PTR + INDEX}). 7578 @end deffn 7579 7580 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 7581 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 7582 @c 7583 @c This is free software: you can redistribute it and/or modify it 7584 @c under the terms of the GNU General Public License as published by 7585 @c the Free Software Foundation, either version 3 of the License, or 7586 @c (at your option) any later version. 7587 @c 7588 @c This program is distributed in the hope that it will be useful, but 7589 @c WITHOUT ANY WARRANTY; without even the implied warranty of 7590 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7591 @c General Public License for more details. 7592 @c 7593 @c You should have received a copy of the GNU General Public License 7594 @c along with this program. If not, see 7595 @c <https://www.gnu.org/licenses/>. 7596 7597 @node Creating and using functions,Function pointers<2>,Expressions,Topic Reference 7598 @anchor{topics/functions doc}@anchor{102}@anchor{topics/functions creating-and-using-functions}@anchor{103} 7599 @section Creating and using functions 7600 7601 7602 @menu 7603 * Params:: 7604 * Functions:: 7605 * Blocks:: 7606 * Statements:: 7607 7608 @end menu 7609 7610 @node Params,Functions,,Creating and using functions 7611 @anchor{topics/functions params}@anchor{104} 7612 @subsection Params 7613 7614 7615 @geindex gcc_jit_param (C type) 7616 @anchor{topics/functions c gcc_jit_param}@anchor{25} 7617 @deffn {C Type} gcc_jit_param 7618 7619 A @cite{gcc_jit_param} represents a parameter to a function. 7620 @end deffn 7621 7622 @geindex gcc_jit_context_new_param (C function) 7623 @anchor{topics/functions c gcc_jit_context_new_param}@anchor{10} 7624 @deffn {C Function} gcc_jit_param * gcc_jit_context_new_param (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, const char@w{ }*name) 7625 7626 In preparation for creating a function, create a new parameter of the 7627 given type and name. 7628 7629 The parameter @code{type} must be non-@cite{void}. 7630 7631 The parameter @code{name} must be non-NULL. The call takes a copy of the 7632 underlying string, so it is valid to pass in a pointer to an on-stack 7633 buffer. 7634 @end deffn 7635 7636 Parameters are lvalues, and thus are also rvalues (and objects), so the 7637 following upcasts are available: 7638 7639 @geindex gcc_jit_param_as_lvalue (C function) 7640 @anchor{topics/functions c gcc_jit_param_as_lvalue}@anchor{105} 7641 @deffn {C Function} gcc_jit_lvalue * gcc_jit_param_as_lvalue (gcc_jit_param@w{ }*param) 7642 7643 Upcasting from param to lvalue. 7644 @end deffn 7645 7646 @geindex gcc_jit_param_as_rvalue (C function) 7647 @anchor{topics/functions c gcc_jit_param_as_rvalue}@anchor{106} 7648 @deffn {C Function} gcc_jit_rvalue * gcc_jit_param_as_rvalue (gcc_jit_param@w{ }*param) 7649 7650 Upcasting from param to rvalue. 7651 @end deffn 7652 7653 @geindex gcc_jit_param_as_object (C function) 7654 @anchor{topics/functions c gcc_jit_param_as_object}@anchor{107} 7655 @deffn {C Function} gcc_jit_object * gcc_jit_param_as_object (gcc_jit_param@w{ }*param) 7656 7657 Upcasting from param to object. 7658 @end deffn 7659 7660 @node Functions,Blocks,Params,Creating and using functions 7661 @anchor{topics/functions functions}@anchor{108} 7662 @subsection Functions 7663 7664 7665 @geindex gcc_jit_function (C type) 7666 @anchor{topics/functions c gcc_jit_function}@anchor{29} 7667 @deffn {C Type} gcc_jit_function 7668 7669 A @cite{gcc_jit_function} represents a function - either one that were 7670 creating ourselves, or one that were referencing. 7671 @end deffn 7672 7673 @geindex gcc_jit_context_new_function (C function) 7674 @anchor{topics/functions c gcc_jit_context_new_function}@anchor{11} 7675 @deffn {C Function} gcc_jit_function * gcc_jit_context_new_function (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_function_kind@w{ }kind, gcc_jit_type@w{ }*return_type, const char@w{ }*name, int@w{ }num_params, gcc_jit_param@w{ }**params, int@w{ }is_variadic) 7676 7677 Create a gcc_jit_function with the given name and parameters. 7678 7679 @geindex gcc_jit_function_kind (C type) 7680 @anchor{topics/functions c gcc_jit_function_kind}@anchor{109} 7681 @deffn {C Type} enum gcc_jit_function_kind 7682 @end deffn 7683 7684 This enum controls the kind of function created, and has the following 7685 values: 7686 7687 @quotation 7688 7689 @geindex GCC_JIT_FUNCTION_EXPORTED (C macro) 7690 @anchor{topics/functions c GCC_JIT_FUNCTION_EXPORTED}@anchor{10a} 7691 @deffn {C Macro} GCC_JIT_FUNCTION_EXPORTED 7692 7693 Function is defined by the client code and visible 7694 by name outside of the JIT. 7695 7696 This value is required if you want to extract machine code 7697 for this function from a @ref{16,,gcc_jit_result} via 7698 @ref{17,,gcc_jit_result_get_code()}. 7699 @end deffn 7700 7701 @geindex GCC_JIT_FUNCTION_INTERNAL (C macro) 7702 @anchor{topics/functions c GCC_JIT_FUNCTION_INTERNAL}@anchor{10b} 7703 @deffn {C Macro} GCC_JIT_FUNCTION_INTERNAL 7704 7705 Function is defined by the client code, but is invisible 7706 outside of the JIT. Analogous to a static function. 7707 @end deffn 7708 7709 @geindex GCC_JIT_FUNCTION_IMPORTED (C macro) 7710 @anchor{topics/functions c GCC_JIT_FUNCTION_IMPORTED}@anchor{10c} 7711 @deffn {C Macro} GCC_JIT_FUNCTION_IMPORTED 7712 7713 Function is not defined by the client code; were merely 7714 referring to it. Analogous to using an extern function from a 7715 header file. 7716 @end deffn 7717 7718 @geindex GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro) 7719 @anchor{topics/functions c GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{10d} 7720 @deffn {C Macro} GCC_JIT_FUNCTION_ALWAYS_INLINE 7721 7722 Function is only ever inlined into other functions, and is 7723 invisible outside of the JIT. 7724 7725 Analogous to prefixing with @code{inline} and adding 7726 @code{__attribute__((always_inline))} 7727 7728 Inlining will only occur when the optimization level is 7729 above 0; when optimization is off, this is essentially the 7730 same as GCC_JIT_FUNCTION_INTERNAL. 7731 @end deffn 7732 @end quotation 7733 7734 The parameter @code{name} must be non-NULL. The call takes a copy of the 7735 underlying string, so it is valid to pass in a pointer to an on-stack 7736 buffer. 7737 @end deffn 7738 7739 @geindex gcc_jit_context_get_builtin_function (C function) 7740 @anchor{topics/functions c gcc_jit_context_get_builtin_function}@anchor{10e} 7741 @deffn {C Function} gcc_jit_function * gcc_jit_context_get_builtin_function (gcc_jit_context@w{ }*ctxt, const char@w{ }*name) 7742 7743 Get the @ref{29,,gcc_jit_function} for the built-in function with the 7744 given name. For example: 7745 7746 @example 7747 gcc_jit_function *fn 7748 = gcc_jit_context_get_builtin_function (ctxt, "__builtin_memcpy"); 7749 @end example 7750 7751 @cartouche 7752 @quotation Note 7753 Due to technical limitations with how libgccjit interacts with 7754 the insides of GCC, not all built-in functions are supported. More 7755 precisely, not all types are supported for parameters of built-in 7756 functions from libgccjit. Attempts to get a built-in function that 7757 uses such a parameter will lead to an error being emitted within 7758 the context. 7759 @end quotation 7760 @end cartouche 7761 @end deffn 7762 7763 @geindex gcc_jit_function_as_object (C function) 7764 @anchor{topics/functions c gcc_jit_function_as_object}@anchor{10f} 7765 @deffn {C Function} gcc_jit_object * gcc_jit_function_as_object (gcc_jit_function@w{ }*func) 7766 7767 Upcasting from function to object. 7768 @end deffn 7769 7770 @geindex gcc_jit_function_get_param (C function) 7771 @anchor{topics/functions c gcc_jit_function_get_param}@anchor{110} 7772 @deffn {C Function} gcc_jit_param * gcc_jit_function_get_param (gcc_jit_function@w{ }*func, int@w{ }index) 7773 7774 Get the param of the given index (0-based). 7775 @end deffn 7776 7777 @geindex gcc_jit_function_dump_to_dot (C function) 7778 @anchor{topics/functions c gcc_jit_function_dump_to_dot}@anchor{33} 7779 @deffn {C Function} void gcc_jit_function_dump_to_dot (gcc_jit_function@w{ }*func, const char@w{ }*path) 7780 7781 Emit the function in graphviz format to the given path. 7782 @end deffn 7783 7784 @geindex gcc_jit_function_new_local (C function) 7785 @anchor{topics/functions c gcc_jit_function_new_local}@anchor{26} 7786 @deffn {C Function} gcc_jit_lvalue * gcc_jit_function_new_local (gcc_jit_function@w{ }*func, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, const char@w{ }*name) 7787 7788 Create a new local variable within the function, of the given type and 7789 name. 7790 7791 The parameter @code{type} must be non-@cite{void}. 7792 7793 The parameter @code{name} must be non-NULL. The call takes a copy of the 7794 underlying string, so it is valid to pass in a pointer to an on-stack 7795 buffer. 7796 @end deffn 7797 7798 @geindex gcc_jit_function_get_param_count (C function) 7799 @anchor{topics/functions c gcc_jit_function_get_param_count}@anchor{111} 7800 @deffn {C Function} size_t gcc_jit_function_get_param_count (gcc_jit_function@w{ }*func) 7801 7802 Get the number of parameters of the function. 7803 @end deffn 7804 7805 @geindex gcc_jit_function_get_return_type (C function) 7806 @anchor{topics/functions c gcc_jit_function_get_return_type}@anchor{112} 7807 @deffn {C Function} gcc_jit_type * gcc_jit_function_get_return_type (gcc_jit_function@w{ }*func) 7808 7809 Get the return type of the function. 7810 7811 The API entrypoints relating to getting info about parameters and return 7812 types: 7813 7814 @quotation 7815 7816 7817 @itemize * 7818 7819 @item 7820 @ref{112,,gcc_jit_function_get_return_type()} 7821 7822 @item 7823 @ref{111,,gcc_jit_function_get_param_count()} 7824 @end itemize 7825 @end quotation 7826 7827 were added in @ref{a8,,LIBGCCJIT_ABI_16}; you can test for their presence 7828 using 7829 7830 @example 7831 #ifdef LIBGCCJIT_HAVE_REFLECTION 7832 @end example 7833 7834 @geindex gcc_jit_case (C type) 7835 @anchor{topics/functions c gcc_jit_case}@anchor{113} 7836 @deffn {C Type} gcc_jit_case 7837 @end deffn 7838 @end deffn 7839 7840 @node Blocks,Statements,Functions,Creating and using functions 7841 @anchor{topics/functions blocks}@anchor{114} 7842 @subsection Blocks 7843 7844 7845 @geindex gcc_jit_block (C type) 7846 @anchor{topics/functions c gcc_jit_block}@anchor{28} 7847 @deffn {C Type} gcc_jit_block 7848 7849 A @cite{gcc_jit_block} represents a basic block within a function i.e. a 7850 sequence of statements with a single entry point and a single exit 7851 point. 7852 7853 The first basic block that you create within a function will 7854 be the entrypoint. 7855 7856 Each basic block that you create within a function must be 7857 terminated, either with a conditional, a jump, a return, or a 7858 switch. 7859 7860 Its legal to have multiple basic blocks that return within 7861 one function. 7862 @end deffn 7863 7864 @geindex gcc_jit_function_new_block (C function) 7865 @anchor{topics/functions c gcc_jit_function_new_block}@anchor{115} 7866 @deffn {C Function} gcc_jit_block * gcc_jit_function_new_block (gcc_jit_function@w{ }*func, const char@w{ }*name) 7867 7868 Create a basic block of the given name. The name may be NULL, but 7869 providing meaningful names is often helpful when debugging: it may 7870 show up in dumps of the internal representation, and in error 7871 messages. It is copied, so the input buffer does not need to outlive 7872 the call; you can pass in a pointer to an on-stack buffer, e.g.: 7873 7874 @example 7875 for (pc = 0; pc < fn->fn_num_ops; pc++) 7876 @{ 7877 char buf[16]; 7878 sprintf (buf, "instr%i", pc); 7879 state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); 7880 @} 7881 @end example 7882 @end deffn 7883 7884 @geindex gcc_jit_block_as_object (C function) 7885 @anchor{topics/functions c gcc_jit_block_as_object}@anchor{116} 7886 @deffn {C Function} gcc_jit_object * gcc_jit_block_as_object (gcc_jit_block@w{ }*block) 7887 7888 Upcast from block to object. 7889 @end deffn 7890 7891 @geindex gcc_jit_block_get_function (C function) 7892 @anchor{topics/functions c gcc_jit_block_get_function}@anchor{117} 7893 @deffn {C Function} gcc_jit_function * gcc_jit_block_get_function (gcc_jit_block@w{ }*block) 7894 7895 Which function is this block within? 7896 @end deffn 7897 7898 @node Statements,,Blocks,Creating and using functions 7899 @anchor{topics/functions statements}@anchor{118} 7900 @subsection Statements 7901 7902 7903 @geindex gcc_jit_block_add_eval (C function) 7904 @anchor{topics/functions c gcc_jit_block_add_eval}@anchor{d8} 7905 @deffn {C Function} void gcc_jit_block_add_eval (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue) 7906 7907 Add evaluation of an rvalue, discarding the result 7908 (e.g. a function call that returns void). 7909 7910 This is equivalent to this C code: 7911 7912 @example 7913 (void)expression; 7914 @end example 7915 @end deffn 7916 7917 @geindex gcc_jit_block_add_assignment (C function) 7918 @anchor{topics/functions c gcc_jit_block_add_assignment}@anchor{2a} 7919 @deffn {C Function} void gcc_jit_block_add_assignment (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_lvalue@w{ }*lvalue, gcc_jit_rvalue@w{ }*rvalue) 7920 7921 Add evaluation of an rvalue, assigning the result to the given 7922 lvalue. 7923 7924 This is roughly equivalent to this C code: 7925 7926 @example 7927 lvalue = rvalue; 7928 @end example 7929 @end deffn 7930 7931 @geindex gcc_jit_block_add_assignment_op (C function) 7932 @anchor{topics/functions c gcc_jit_block_add_assignment_op}@anchor{2e} 7933 @deffn {C Function} void gcc_jit_block_add_assignment_op (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_lvalue@w{ }*lvalue, enum gcc_jit_binary_op@w{ }op, gcc_jit_rvalue@w{ }*rvalue) 7934 7935 Add evaluation of an rvalue, using the result to modify an 7936 lvalue. 7937 7938 This is analogous to += and friends: 7939 7940 @example 7941 lvalue += rvalue; 7942 lvalue *= rvalue; 7943 lvalue /= rvalue; 7944 @end example 7945 7946 etc. For example: 7947 7948 @example 7949 /* "i++" */ 7950 gcc_jit_block_add_assignment_op ( 7951 loop_body, NULL, 7952 i, 7953 GCC_JIT_BINARY_OP_PLUS, 7954 gcc_jit_context_one (ctxt, int_type)); 7955 @end example 7956 @end deffn 7957 7958 @geindex gcc_jit_block_add_comment (C function) 7959 @anchor{topics/functions c gcc_jit_block_add_comment}@anchor{3d} 7960 @deffn {C Function} void gcc_jit_block_add_comment (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*text) 7961 7962 Add a no-op textual comment to the internal representation of the 7963 code. It will be optimized away, but will be visible in the dumps 7964 seen via @ref{66,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} 7965 and @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, 7966 and thus may be of use when debugging how your projects internal 7967 representation gets converted to the libgccjit IR. 7968 7969 The parameter @code{text} must be non-NULL. It is copied, so the input 7970 buffer does not need to outlive the call. For example: 7971 7972 @example 7973 char buf[100]; 7974 snprintf (buf, sizeof (buf), 7975 "op%i: %s", 7976 pc, opcode_names[op->op_opcode]); 7977 gcc_jit_block_add_comment (block, loc, buf); 7978 @end example 7979 @end deffn 7980 7981 @geindex gcc_jit_block_end_with_conditional (C function) 7982 @anchor{topics/functions c gcc_jit_block_end_with_conditional}@anchor{2d} 7983 @deffn {C Function} void gcc_jit_block_end_with_conditional (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*boolval, gcc_jit_block@w{ }*on_true, gcc_jit_block@w{ }*on_false) 7984 7985 Terminate a block by adding evaluation of an rvalue, branching on the 7986 result to the appropriate successor block. 7987 7988 This is roughly equivalent to this C code: 7989 7990 @example 7991 if (boolval) 7992 goto on_true; 7993 else 7994 goto on_false; 7995 @end example 7996 7997 block, boolval, on_true, and on_false must be non-NULL. 7998 @end deffn 7999 8000 @geindex gcc_jit_block_end_with_jump (C function) 8001 @anchor{topics/functions c gcc_jit_block_end_with_jump}@anchor{119} 8002 @deffn {C Function} void gcc_jit_block_end_with_jump (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_block@w{ }*target) 8003 8004 Terminate a block by adding a jump to the given target block. 8005 8006 This is roughly equivalent to this C code: 8007 8008 @example 8009 goto target; 8010 @end example 8011 @end deffn 8012 8013 @geindex gcc_jit_block_end_with_return (C function) 8014 @anchor{topics/functions c gcc_jit_block_end_with_return}@anchor{11a} 8015 @deffn {C Function} void gcc_jit_block_end_with_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue) 8016 8017 Terminate a block by adding evaluation of an rvalue, returning the value. 8018 8019 This is roughly equivalent to this C code: 8020 8021 @example 8022 return expression; 8023 @end example 8024 @end deffn 8025 8026 @geindex gcc_jit_block_end_with_void_return (C function) 8027 @anchor{topics/functions c gcc_jit_block_end_with_void_return}@anchor{11b} 8028 @deffn {C Function} void gcc_jit_block_end_with_void_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc) 8029 8030 Terminate a block by adding a valueless return, for use within a function 8031 with void return type. 8032 8033 This is equivalent to this C code: 8034 8035 @example 8036 return; 8037 @end example 8038 @end deffn 8039 8040 @geindex gcc_jit_block_end_with_switch (C function) 8041 @anchor{topics/functions c gcc_jit_block_end_with_switch}@anchor{11c} 8042 @deffn {C Function} void gcc_jit_block_end_with_switch (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*expr, gcc_jit_block@w{ }*default_block, int@w{ }num_cases, gcc_jit_case@w{ }**cases) 8043 8044 Terminate a block by adding evalation of an rvalue, then performing 8045 a multiway branch. 8046 8047 This is roughly equivalent to this C code: 8048 8049 @example 8050 switch (expr) 8051 @{ 8052 default: 8053 goto default_block; 8054 8055 case C0.min_value ... C0.max_value: 8056 goto C0.dest_block; 8057 8058 case C1.min_value ... C1.max_value: 8059 goto C1.dest_block; 8060 8061 ...etc... 8062 8063 case C[N - 1].min_value ... C[N - 1].max_value: 8064 goto C[N - 1].dest_block; 8065 @} 8066 @end example 8067 8068 @code{block}, @code{expr}, @code{default_block} and @code{cases} must all be 8069 non-NULL. 8070 8071 @code{expr} must be of the same integer type as all of the @code{min_value} 8072 and @code{max_value} within the cases. 8073 8074 @code{num_cases} must be >= 0. 8075 8076 The ranges of the cases must not overlap (or have duplicate 8077 values). 8078 8079 The API entrypoints relating to switch statements and cases: 8080 8081 @quotation 8082 8083 8084 @itemize * 8085 8086 @item 8087 @ref{11c,,gcc_jit_block_end_with_switch()} 8088 8089 @item 8090 @ref{11d,,gcc_jit_case_as_object()} 8091 8092 @item 8093 @ref{11e,,gcc_jit_context_new_case()} 8094 @end itemize 8095 @end quotation 8096 8097 were added in @ref{11f,,LIBGCCJIT_ABI_3}; you can test for their presence 8098 using 8099 8100 @example 8101 #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS 8102 @end example 8103 8104 @geindex gcc_jit_case (C type) 8105 8106 @deffn {C Type} gcc_jit_case 8107 @end deffn 8108 8109 A @cite{gcc_jit_case} represents a case within a switch statement, and 8110 is created within a particular @ref{8,,gcc_jit_context} using 8111 @ref{11e,,gcc_jit_context_new_case()}. 8112 8113 Each case expresses a multivalued range of integer values. You 8114 can express single-valued cases by passing in the same value for 8115 both @cite{min_value} and @cite{max_value}. 8116 8117 @geindex gcc_jit_context_new_case (C function) 8118 @anchor{topics/functions c gcc_jit_context_new_case}@anchor{11e} 8119 @deffn {C Function} gcc_jit_case * gcc_jit_context_new_case (gcc_jit_context@w{ }*ctxt, gcc_jit_rvalue@w{ }*min_value, gcc_jit_rvalue@w{ }*max_value, gcc_jit_block@w{ }*dest_block) 8120 8121 Create a new gcc_jit_case instance for use in a switch statement. 8122 @cite{min_value} and @cite{max_value} must be constants of an integer type, 8123 which must match that of the expression of the switch statement. 8124 8125 @cite{dest_block} must be within the same function as the switch 8126 statement. 8127 @end deffn 8128 8129 @geindex gcc_jit_case_as_object (C function) 8130 @anchor{topics/functions c gcc_jit_case_as_object}@anchor{11d} 8131 @deffn {C Function} gcc_jit_object * gcc_jit_case_as_object (gcc_jit_case@w{ }*case_) 8132 8133 Upcast from a case to an object. 8134 @end deffn 8135 8136 Heres an example of creating a switch statement: 8137 8138 @quotation 8139 8140 @example 8141 8142 void 8143 create_code (gcc_jit_context *ctxt, void *user_data) 8144 @{ 8145 /* Let's try to inject the equivalent of: 8146 int 8147 test_switch (int x) 8148 @{ 8149 switch (x) 8150 @{ 8151 case 0 ... 5: 8152 return 3; 8153 8154 case 25 ... 27: 8155 return 4; 8156 8157 case -42 ... -17: 8158 return 83; 8159 8160 case 40: 8161 return 8; 8162 8163 default: 8164 return 10; 8165 @} 8166 @} 8167 */ 8168 gcc_jit_type *t_int = 8169 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 8170 gcc_jit_type *return_type = t_int; 8171 gcc_jit_param *x = 8172 gcc_jit_context_new_param (ctxt, NULL, t_int, "x"); 8173 gcc_jit_param *params[1] = @{x@}; 8174 gcc_jit_function *func = 8175 gcc_jit_context_new_function (ctxt, NULL, 8176 GCC_JIT_FUNCTION_EXPORTED, 8177 return_type, 8178 "test_switch", 8179 1, params, 0); 8180 8181 gcc_jit_block *b_initial = 8182 gcc_jit_function_new_block (func, "initial"); 8183 8184 gcc_jit_block *b_default = 8185 gcc_jit_function_new_block (func, "default"); 8186 gcc_jit_block *b_case_0_5 = 8187 gcc_jit_function_new_block (func, "case_0_5"); 8188 gcc_jit_block *b_case_25_27 = 8189 gcc_jit_function_new_block (func, "case_25_27"); 8190 gcc_jit_block *b_case_m42_m17 = 8191 gcc_jit_function_new_block (func, "case_m42_m17"); 8192 gcc_jit_block *b_case_40 = 8193 gcc_jit_function_new_block (func, "case_40"); 8194 8195 gcc_jit_case *cases[4] = @{ 8196 gcc_jit_context_new_case ( 8197 ctxt, 8198 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0), 8199 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5), 8200 b_case_0_5), 8201 gcc_jit_context_new_case ( 8202 ctxt, 8203 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 25), 8204 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 27), 8205 b_case_25_27), 8206 gcc_jit_context_new_case ( 8207 ctxt, 8208 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -42), 8209 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -17), 8210 b_case_m42_m17), 8211 gcc_jit_context_new_case ( 8212 ctxt, 8213 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40), 8214 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40), 8215 b_case_40) 8216 @}; 8217 gcc_jit_block_end_with_switch ( 8218 b_initial, NULL, 8219 gcc_jit_param_as_rvalue (x), 8220 b_default, 8221 4, cases); 8222 8223 gcc_jit_block_end_with_return ( 8224 b_case_0_5, NULL, 8225 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3)); 8226 gcc_jit_block_end_with_return ( 8227 b_case_25_27, NULL, 8228 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4)); 8229 gcc_jit_block_end_with_return ( 8230 b_case_m42_m17, NULL, 8231 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 83)); 8232 gcc_jit_block_end_with_return ( 8233 b_case_40, NULL, 8234 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 8)); 8235 gcc_jit_block_end_with_return ( 8236 b_default, NULL, 8237 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10)); 8238 @} 8239 8240 @end example 8241 @end quotation 8242 @end deffn 8243 8244 See also @ref{120,,gcc_jit_extended_asm} for entrypoints for adding inline 8245 assembler statements to a function. 8246 8247 @c Copyright (C) 2017-2022 Free Software Foundation, Inc. 8248 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 8249 @c 8250 @c This is free software: you can redistribute it and/or modify it 8251 @c under the terms of the GNU General Public License as published by 8252 @c the Free Software Foundation, either version 3 of the License, or 8253 @c (at your option) any later version. 8254 @c 8255 @c This program is distributed in the hope that it will be useful, but 8256 @c WITHOUT ANY WARRANTY; without even the implied warranty of 8257 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8258 @c General Public License for more details. 8259 @c 8260 @c You should have received a copy of the GNU General Public License 8261 @c along with this program. If not, see 8262 @c <https://www.gnu.org/licenses/>. 8263 8264 @node Function pointers<2>,Source Locations,Creating and using functions,Topic Reference 8265 @anchor{topics/function-pointers doc}@anchor{121}@anchor{topics/function-pointers function-pointers}@anchor{122} 8266 @section Function pointers 8267 8268 8269 You can generate calls that use a function pointer via 8270 @ref{d9,,gcc_jit_context_new_call_through_ptr()}. 8271 8272 To do requires a @ref{13,,gcc_jit_rvalue} of the correct function pointer type. 8273 8274 Function pointers for a @ref{29,,gcc_jit_function} can be obtained 8275 via @ref{dd,,gcc_jit_function_get_address()}. 8276 8277 @geindex gcc_jit_function_get_address (C function) 8278 @anchor{topics/function-pointers c gcc_jit_function_get_address}@anchor{dd} 8279 @deffn {C Function} gcc_jit_rvalue * gcc_jit_function_get_address (gcc_jit_function@w{ }*fn, gcc_jit_location@w{ }*loc) 8280 8281 Get the address of a function as an rvalue, of function pointer 8282 type. 8283 8284 This entrypoint was added in @ref{123,,LIBGCCJIT_ABI_9}; you can test 8285 for its presence using 8286 8287 @example 8288 #ifdef LIBGCCJIT_HAVE_gcc_jit_function_get_address 8289 @end example 8290 @end deffn 8291 8292 Alternatively, given an existing function, you can obtain a pointer 8293 to it in @ref{13,,gcc_jit_rvalue} form using 8294 @ref{b3,,gcc_jit_context_new_rvalue_from_ptr()}, using a function pointer 8295 type obtained using @ref{97,,gcc_jit_context_new_function_ptr_type()}. 8296 8297 Heres an example of creating a function pointer type corresponding to Cs 8298 @code{void (*) (int, int, int)}: 8299 8300 @example 8301 gcc_jit_type *void_type = 8302 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); 8303 gcc_jit_type *int_type = 8304 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 8305 8306 /* Build the function ptr type. */ 8307 gcc_jit_type *param_types[3]; 8308 param_types[0] = int_type; 8309 param_types[1] = int_type; 8310 param_types[2] = int_type; 8311 8312 gcc_jit_type *fn_ptr_type = 8313 gcc_jit_context_new_function_ptr_type (ctxt, NULL, 8314 void_type, 8315 3, param_types, 0); 8316 @end example 8317 8318 @geindex gcc_jit_context_new_function_ptr_type (C function) 8319 @anchor{topics/function-pointers c gcc_jit_context_new_function_ptr_type}@anchor{97} 8320 @deffn {C Function} gcc_jit_type * gcc_jit_context_new_function_ptr_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*return_type, int@w{ }num_params, gcc_jit_type@w{ }**param_types, int@w{ }is_variadic) 8321 8322 Generate a @ref{a,,gcc_jit_type} for a function pointer with the 8323 given return type and parameters. 8324 8325 Each of @cite{param_types} must be non-@cite{void}; @cite{return_type} may be @cite{void}. 8326 @end deffn 8327 8328 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 8329 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 8330 @c 8331 @c This is free software: you can redistribute it and/or modify it 8332 @c under the terms of the GNU General Public License as published by 8333 @c the Free Software Foundation, either version 3 of the License, or 8334 @c (at your option) any later version. 8335 @c 8336 @c This program is distributed in the hope that it will be useful, but 8337 @c WITHOUT ANY WARRANTY; without even the implied warranty of 8338 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8339 @c General Public License for more details. 8340 @c 8341 @c You should have received a copy of the GNU General Public License 8342 @c along with this program. If not, see 8343 @c <https://www.gnu.org/licenses/>. 8344 8345 @node Source Locations,Compiling a context,Function pointers<2>,Topic Reference 8346 @anchor{topics/locations doc}@anchor{124}@anchor{topics/locations source-locations}@anchor{125} 8347 @section Source Locations 8348 8349 8350 @geindex gcc_jit_location (C type) 8351 @anchor{topics/locations c gcc_jit_location}@anchor{3b} 8352 @deffn {C Type} gcc_jit_location 8353 8354 A @cite{gcc_jit_location} encapsulates a source code location, so that 8355 you can (optionally) associate locations in your language with 8356 statements in the JIT-compiled code, allowing the debugger to 8357 single-step through your language. 8358 8359 @cite{gcc_jit_location} instances are optional: you can always pass NULL to 8360 any API entrypoint accepting one. 8361 8362 You can construct them using @ref{41,,gcc_jit_context_new_location()}. 8363 8364 You need to enable @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 8365 @ref{8,,gcc_jit_context} for these locations to actually be usable by 8366 the debugger: 8367 8368 @example 8369 gcc_jit_context_set_bool_option ( 8370 ctxt, 8371 GCC_JIT_BOOL_OPTION_DEBUGINFO, 8372 1); 8373 @end example 8374 @end deffn 8375 8376 @geindex gcc_jit_context_new_location (C function) 8377 @anchor{topics/locations c gcc_jit_context_new_location}@anchor{41} 8378 @deffn {C Function} gcc_jit_location * gcc_jit_context_new_location (gcc_jit_context@w{ }*ctxt, const char@w{ }*filename, int@w{ }line, int@w{ }column) 8379 8380 Create a @cite{gcc_jit_location} instance representing the given source 8381 location. 8382 8383 The parameter @code{filename} must be non-NULL. The call takes a copy of 8384 the underlying string, so it is valid to pass in a pointer to an 8385 on-stack buffer. 8386 @end deffn 8387 8388 @menu 8389 * Faking it:: 8390 8391 @end menu 8392 8393 @node Faking it,,,Source Locations 8394 @anchor{topics/locations faking-it}@anchor{126} 8395 @subsection Faking it 8396 8397 8398 If you dont have source code for your internal representation, but need 8399 to debug, you can generate a C-like representation of the functions in 8400 your context using @ref{5a,,gcc_jit_context_dump_to_file()}: 8401 8402 @example 8403 gcc_jit_context_dump_to_file (ctxt, "/tmp/something.c", 8404 1 /* update_locations */); 8405 @end example 8406 8407 This will dump C-like code to the given path. If the @cite{update_locations} 8408 argument is true, this will also set up @cite{gcc_jit_location} information 8409 throughout the context, pointing at the dump file as if it were a source 8410 file, giving you @emph{something} you can step through in the debugger. 8411 8412 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 8413 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 8414 @c 8415 @c This is free software: you can redistribute it and/or modify it 8416 @c under the terms of the GNU General Public License as published by 8417 @c the Free Software Foundation, either version 3 of the License, or 8418 @c (at your option) any later version. 8419 @c 8420 @c This program is distributed in the hope that it will be useful, but 8421 @c WITHOUT ANY WARRANTY; without even the implied warranty of 8422 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8423 @c General Public License for more details. 8424 @c 8425 @c You should have received a copy of the GNU General Public License 8426 @c along with this program. If not, see 8427 @c <https://www.gnu.org/licenses/>. 8428 8429 @node Compiling a context,ABI and API compatibility,Source Locations,Topic Reference 8430 @anchor{topics/compilation doc}@anchor{127}@anchor{topics/compilation compiling-a-context}@anchor{128} 8431 @section Compiling a context 8432 8433 8434 Once populated, a @ref{8,,gcc_jit_context *} can be compiled to 8435 machine code, either in-memory via @ref{15,,gcc_jit_context_compile()} or 8436 to disk via @ref{4a,,gcc_jit_context_compile_to_file()}. 8437 8438 You can compile a context multiple times (using either form of 8439 compilation), although any errors that occur on the context will 8440 prevent any future compilation of that context. 8441 8442 @menu 8443 * In-memory compilation:: 8444 * Ahead-of-time compilation:: 8445 8446 @end menu 8447 8448 @node In-memory compilation,Ahead-of-time compilation,,Compiling a context 8449 @anchor{topics/compilation in-memory-compilation}@anchor{129} 8450 @subsection In-memory compilation 8451 8452 8453 @geindex gcc_jit_context_compile (C function) 8454 @anchor{topics/compilation c gcc_jit_context_compile}@anchor{15} 8455 @deffn {C Function} gcc_jit_result * gcc_jit_context_compile (gcc_jit_context@w{ }*ctxt) 8456 8457 This calls into GCC and builds the code, returning a 8458 @cite{gcc_jit_result *}. 8459 8460 If the result is non-NULL, the caller becomes responsible for 8461 calling @ref{39,,gcc_jit_result_release()} on it once theyre done 8462 with it. 8463 @end deffn 8464 8465 @geindex gcc_jit_result (C type) 8466 @anchor{topics/compilation c gcc_jit_result}@anchor{16} 8467 @deffn {C Type} gcc_jit_result 8468 8469 A @cite{gcc_jit_result} encapsulates the result of compiling a context 8470 in-memory, and the lifetimes of any machine code functions or globals 8471 that are within the result. 8472 @end deffn 8473 8474 @geindex gcc_jit_result_get_code (C function) 8475 @anchor{topics/compilation c gcc_jit_result_get_code}@anchor{17} 8476 @deffn {C Function} void * gcc_jit_result_get_code (gcc_jit_result@w{ }*result, const char@w{ }*funcname) 8477 8478 Locate a given function within the built machine code. 8479 8480 Functions are looked up by name. For this to succeed, a function 8481 with a name matching @cite{funcname} must have been created on 8482 @cite{result}s context (or a parent context) via a call to 8483 @ref{11,,gcc_jit_context_new_function()} with @cite{kind} 8484 @ref{10a,,GCC_JIT_FUNCTION_EXPORTED}: 8485 8486 @example 8487 gcc_jit_context_new_function (ctxt, 8488 any_location, /* or NULL */ 8489 /* Required for func to be visible to 8490 gcc_jit_result_get_code: */ 8491 GCC_JIT_FUNCTION_EXPORTED, 8492 any_return_type, 8493 /* Must string-compare equal: */ 8494 funcname, 8495 /* etc */); 8496 @end example 8497 8498 If such a function is not found (or @cite{result} or @cite{funcname} are 8499 @code{NULL}), an error message will be emitted on stderr and 8500 @code{NULL} will be returned. 8501 8502 If the function is found, the result will need to be cast to a 8503 function pointer of the correct type before it can be called. 8504 8505 Note that the resulting machine code becomes invalid after 8506 @ref{39,,gcc_jit_result_release()} is called on the 8507 @ref{16,,gcc_jit_result *}; attempting to call it after that may lead 8508 to a segmentation fault. 8509 @end deffn 8510 8511 @geindex gcc_jit_result_get_global (C function) 8512 @anchor{topics/compilation c gcc_jit_result_get_global}@anchor{f8} 8513 @deffn {C Function} void * gcc_jit_result_get_global (gcc_jit_result@w{ }*result, const char@w{ }*name) 8514 8515 Locate a given global within the built machine code. 8516 8517 Globals are looked up by name. For this to succeed, a global 8518 with a name matching @cite{name} must have been created on 8519 @cite{result}s context (or a parent context) via a call to 8520 @ref{f5,,gcc_jit_context_new_global()} with @cite{kind} 8521 @ref{f7,,GCC_JIT_GLOBAL_EXPORTED}. 8522 8523 If the global is found, the result will need to be cast to a 8524 pointer of the correct type before it can be called. 8525 8526 This is a @emph{pointer} to the global, so e.g. for an @code{int} this is 8527 an @code{int *}. 8528 8529 For example, given an @code{int foo;} created this way: 8530 8531 @example 8532 gcc_jit_lvalue *exported_global = 8533 gcc_jit_context_new_global (ctxt, 8534 any_location, /* or NULL */ 8535 GCC_JIT_GLOBAL_EXPORTED, 8536 int_type, 8537 "foo"); 8538 @end example 8539 8540 we can access it like this: 8541 8542 @example 8543 int *ptr_to_foo = 8544 (int *)gcc_jit_result_get_global (result, "foo"); 8545 @end example 8546 8547 If such a global is not found (or @cite{result} or @cite{name} are 8548 @code{NULL}), an error message will be emitted on stderr and 8549 @code{NULL} will be returned. 8550 8551 Note that the resulting address becomes invalid after 8552 @ref{39,,gcc_jit_result_release()} is called on the 8553 @ref{16,,gcc_jit_result *}; attempting to use it after that may lead 8554 to a segmentation fault. 8555 @end deffn 8556 8557 @geindex gcc_jit_result_release (C function) 8558 @anchor{topics/compilation c gcc_jit_result_release}@anchor{39} 8559 @deffn {C Function} void gcc_jit_result_release (gcc_jit_result@w{ }*result) 8560 8561 Once were done with the code, this unloads the built .so file. 8562 This cleans up the result; after calling this, its no longer 8563 valid to use the result, or any code or globals that were obtained 8564 by calling @ref{17,,gcc_jit_result_get_code()} or 8565 @ref{f8,,gcc_jit_result_get_global()} on it. 8566 @end deffn 8567 8568 @node Ahead-of-time compilation,,In-memory compilation,Compiling a context 8569 @anchor{topics/compilation ahead-of-time-compilation}@anchor{12a} 8570 @subsection Ahead-of-time compilation 8571 8572 8573 Although libgccjit is primarily aimed at just-in-time compilation, it 8574 can also be used for implementing more traditional ahead-of-time 8575 compilers, via the @ref{4a,,gcc_jit_context_compile_to_file()} 8576 API entrypoint. 8577 8578 For linking in object files, use @ref{76,,gcc_jit_context_add_driver_option()}. 8579 8580 @geindex gcc_jit_context_compile_to_file (C function) 8581 @anchor{topics/compilation c gcc_jit_context_compile_to_file}@anchor{4a} 8582 @deffn {C Function} void gcc_jit_context_compile_to_file (gcc_jit_context@w{ }*ctxt, enum gcc_jit_output_kind@w{ }output_kind, const char@w{ }*output_path) 8583 8584 Compile the @ref{8,,gcc_jit_context *} to a file of the given 8585 kind. 8586 @end deffn 8587 8588 @ref{4a,,gcc_jit_context_compile_to_file()} ignores the suffix of 8589 @code{output_path}, and insteads uses the given 8590 @code{enum gcc_jit_output_kind} to decide what to do. 8591 8592 @cartouche 8593 @quotation Note 8594 This is different from the @code{gcc} program, which does make use of the 8595 suffix of the output file when determining what to do. 8596 @end quotation 8597 @end cartouche 8598 8599 @geindex gcc_jit_output_kind (C type) 8600 @anchor{topics/compilation c gcc_jit_output_kind}@anchor{12b} 8601 @deffn {C Type} enum gcc_jit_output_kind 8602 @end deffn 8603 8604 The available kinds of output are: 8605 8606 8607 @multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxx} 8608 @headitem 8609 8610 Output kind 8611 8612 @tab 8613 8614 Typical suffix 8615 8616 @item 8617 8618 @ref{12c,,GCC_JIT_OUTPUT_KIND_ASSEMBLER} 8619 8620 @tab 8621 8622 .s 8623 8624 @item 8625 8626 @ref{12d,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE} 8627 8628 @tab 8629 8630 .o 8631 8632 @item 8633 8634 @ref{12e,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY} 8635 8636 @tab 8637 8638 .so or .dll 8639 8640 @item 8641 8642 @ref{12f,,GCC_JIT_OUTPUT_KIND_EXECUTABLE} 8643 8644 @tab 8645 8646 None, or .exe 8647 8648 @end multitable 8649 8650 8651 @geindex GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro) 8652 @anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{12c} 8653 @deffn {C Macro} GCC_JIT_OUTPUT_KIND_ASSEMBLER 8654 8655 Compile the context to an assembler file. 8656 @end deffn 8657 8658 @geindex GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro) 8659 @anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{12d} 8660 @deffn {C Macro} GCC_JIT_OUTPUT_KIND_OBJECT_FILE 8661 8662 Compile the context to an object file. 8663 @end deffn 8664 8665 @geindex GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro) 8666 @anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{12e} 8667 @deffn {C Macro} GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY 8668 8669 Compile the context to a dynamic library. 8670 @end deffn 8671 8672 @geindex GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro) 8673 @anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{12f} 8674 @deffn {C Macro} GCC_JIT_OUTPUT_KIND_EXECUTABLE 8675 8676 Compile the context to an executable. 8677 @end deffn 8678 8679 @c Copyright (C) 2015-2022 Free Software Foundation, Inc. 8680 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 8681 @c 8682 @c This is free software: you can redistribute it and/or modify it 8683 @c under the terms of the GNU General Public License as published by 8684 @c the Free Software Foundation, either version 3 of the License, or 8685 @c (at your option) any later version. 8686 @c 8687 @c This program is distributed in the hope that it will be useful, but 8688 @c WITHOUT ANY WARRANTY; without even the implied warranty of 8689 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8690 @c General Public License for more details. 8691 @c 8692 @c You should have received a copy of the GNU General Public License 8693 @c along with this program. If not, see 8694 @c <https://www.gnu.org/licenses/>. 8695 8696 @node ABI and API compatibility,Performance,Compiling a context,Topic Reference 8697 @anchor{topics/compatibility doc}@anchor{130}@anchor{topics/compatibility abi-and-api-compatibility}@anchor{131} 8698 @section ABI and API compatibility 8699 8700 8701 The libgccjit developers strive for ABI and API backward-compatibility: 8702 programs built against libgccjit.so stand a good chance of running 8703 without recompilation against newer versions of libgccjit.so, and 8704 ought to recompile without modification against newer versions of 8705 libgccjit.h. 8706 8707 @cartouche 8708 @quotation Note 8709 The libgccjit++.h C++ API is more experimental, and less 8710 locked-down at this time. 8711 @end quotation 8712 @end cartouche 8713 8714 API compatibility is achieved by extending the API rather than changing 8715 it. For ABI compatiblity, we avoid bumping the SONAME, and instead use 8716 symbol versioning to tag each symbol, so that a binary linked against 8717 libgccjit.so is tagged according to the symbols that it uses. 8718 8719 For example, @ref{74,,gcc_jit_context_add_command_line_option()} was added in 8720 @code{LIBGCCJIT_ABI_1}. If a client program uses it, this can be detected 8721 from metadata by using @code{objdump}: 8722 8723 @example 8724 $ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8 8725 8726 Version References: 8727 required from libgccjit.so.0: 8728 0x00824161 0x00 04 LIBGCCJIT_ABI_1 8729 0x00824160 0x00 03 LIBGCCJIT_ABI_0 8730 required from libc.so.6: 8731 @end example 8732 8733 You can see the symbol tags provided by libgccjit.so using @code{objdump}: 8734 8735 @example 8736 $ objdump -p libgccjit.so | less 8737 [...snip...] 8738 Version definitions: 8739 1 0x01 0x0ff81f20 libgccjit.so.0 8740 2 0x00 0x00824160 LIBGCCJIT_ABI_0 8741 3 0x00 0x00824161 LIBGCCJIT_ABI_1 8742 LIBGCCJIT_ABI_0 8743 [...snip...] 8744 @end example 8745 8746 @menu 8747 * Programmatically checking version:: 8748 * ABI symbol tags:: 8749 8750 @end menu 8751 8752 @node Programmatically checking version,ABI symbol tags,,ABI and API compatibility 8753 @anchor{topics/compatibility programmatically-checking-version}@anchor{132} 8754 @subsection Programmatically checking version 8755 8756 8757 Client code can programmatically check libgccjit version using: 8758 8759 @geindex gcc_jit_version_major (C function) 8760 @anchor{topics/compatibility c gcc_jit_version_major}@anchor{133} 8761 @deffn {C Function} int gcc_jit_version_major (void) 8762 8763 Return libgccjit major version. This is analogous to __GNUC__ in C code. 8764 @end deffn 8765 8766 @geindex gcc_jit_version_minor (C function) 8767 @anchor{topics/compatibility c gcc_jit_version_minor}@anchor{134} 8768 @deffn {C Function} int gcc_jit_version_minor (void) 8769 8770 Return libgccjit minor version. This is analogous to 8771 __GNUC_MINOR__ in C code. 8772 @end deffn 8773 8774 @geindex gcc_jit_version_patchlevel (C function) 8775 @anchor{topics/compatibility c gcc_jit_version_patchlevel}@anchor{135} 8776 @deffn {C Function} int gcc_jit_version_patchlevel (void) 8777 8778 Return libgccjit patchlevel version. This is analogous to 8779 __GNUC_PATCHLEVEL__ in C code. 8780 @end deffn 8781 8782 @cartouche 8783 @quotation Note 8784 These entry points has been added with @code{LIBGCCJIT_ABI_13} 8785 (see below). 8786 @end quotation 8787 @end cartouche 8788 8789 @node ABI symbol tags,,Programmatically checking version,ABI and API compatibility 8790 @anchor{topics/compatibility abi-symbol-tags}@anchor{136} 8791 @subsection ABI symbol tags 8792 8793 8794 The initial release of libgccjit (in gcc 5.1) did not use symbol versioning. 8795 8796 Newer releases use the following tags. 8797 8798 @menu 8799 * LIBGCCJIT_ABI_0:: 8800 * LIBGCCJIT_ABI_1:: 8801 * LIBGCCJIT_ABI_2:: 8802 * LIBGCCJIT_ABI_3:: 8803 * LIBGCCJIT_ABI_4:: 8804 * LIBGCCJIT_ABI_5:: 8805 * LIBGCCJIT_ABI_6:: 8806 * LIBGCCJIT_ABI_7:: 8807 * LIBGCCJIT_ABI_8:: 8808 * LIBGCCJIT_ABI_9:: 8809 * LIBGCCJIT_ABI_10:: 8810 * LIBGCCJIT_ABI_11:: 8811 * LIBGCCJIT_ABI_12:: 8812 * LIBGCCJIT_ABI_13:: 8813 * LIBGCCJIT_ABI_14:: 8814 * LIBGCCJIT_ABI_15:: 8815 * LIBGCCJIT_ABI_16:: 8816 * LIBGCCJIT_ABI_17:: 8817 * LIBGCCJIT_ABI_18:: 8818 * LIBGCCJIT_ABI_19:: 8819 * LIBGCCJIT_ABI_20:: 8820 * LIBGCCJIT_ABI_21:: 8821 * LIBGCCJIT_ABI_22:: 8822 * LIBGCCJIT_ABI_23:: 8823 * LIBGCCJIT_ABI_24:: 8824 8825 @end menu 8826 8827 @node LIBGCCJIT_ABI_0,LIBGCCJIT_ABI_1,,ABI symbol tags 8828 @anchor{topics/compatibility id1}@anchor{137}@anchor{topics/compatibility libgccjit-abi-0}@anchor{138} 8829 @subsubsection @code{LIBGCCJIT_ABI_0} 8830 8831 8832 All entrypoints in the initial release of libgccjit are tagged with 8833 @code{LIBGCCJIT_ABI_0}, to signify the transition to symbol versioning. 8834 8835 Binaries built against older copies of @code{libgccjit.so} should 8836 continue to work, with this being handled transparently by the linker 8837 (see this post@footnote{https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html}) 8838 8839 @node LIBGCCJIT_ABI_1,LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_0,ABI symbol tags 8840 @anchor{topics/compatibility id2}@anchor{139}@anchor{topics/compatibility libgccjit-abi-1}@anchor{75} 8841 @subsubsection @code{LIBGCCJIT_ABI_1} 8842 8843 8844 @code{LIBGCCJIT_ABI_1} covers the addition of 8845 @ref{74,,gcc_jit_context_add_command_line_option()} 8846 8847 @node LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_1,ABI symbol tags 8848 @anchor{topics/compatibility id3}@anchor{13a}@anchor{topics/compatibility libgccjit-abi-2}@anchor{6c} 8849 @subsubsection @code{LIBGCCJIT_ABI_2} 8850 8851 8852 @code{LIBGCCJIT_ABI_2} covers the addition of 8853 @ref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()} 8854 8855 @node LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_2,ABI symbol tags 8856 @anchor{topics/compatibility id4}@anchor{13b}@anchor{topics/compatibility libgccjit-abi-3}@anchor{11f} 8857 @subsubsection @code{LIBGCCJIT_ABI_3} 8858 8859 8860 @code{LIBGCCJIT_ABI_3} covers the addition of switch statements via API 8861 entrypoints: 8862 8863 @quotation 8864 8865 8866 @itemize * 8867 8868 @item 8869 @ref{11c,,gcc_jit_block_end_with_switch()} 8870 8871 @item 8872 @ref{11d,,gcc_jit_case_as_object()} 8873 8874 @item 8875 @ref{11e,,gcc_jit_context_new_case()} 8876 @end itemize 8877 @end quotation 8878 8879 @node LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_3,ABI symbol tags 8880 @anchor{topics/compatibility id5}@anchor{13c}@anchor{topics/compatibility libgccjit-abi-4}@anchor{13d} 8881 @subsubsection @code{LIBGCCJIT_ABI_4} 8882 8883 8884 @code{LIBGCCJIT_ABI_4} covers the addition of timers via API 8885 entrypoints: 8886 8887 @quotation 8888 8889 8890 @itemize * 8891 8892 @item 8893 @ref{13e,,gcc_jit_context_get_timer()} 8894 8895 @item 8896 @ref{13f,,gcc_jit_context_set_timer()} 8897 8898 @item 8899 @ref{140,,gcc_jit_timer_new()} 8900 8901 @item 8902 @ref{141,,gcc_jit_timer_release()} 8903 8904 @item 8905 @ref{142,,gcc_jit_timer_push()} 8906 8907 @item 8908 @ref{143,,gcc_jit_timer_pop()} 8909 8910 @item 8911 @ref{144,,gcc_jit_timer_print()} 8912 @end itemize 8913 @end quotation 8914 8915 @node LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_4,ABI symbol tags 8916 @anchor{topics/compatibility id6}@anchor{145}@anchor{topics/compatibility libgccjit-abi-5}@anchor{6e} 8917 @subsubsection @code{LIBGCCJIT_ABI_5} 8918 8919 8920 @code{LIBGCCJIT_ABI_5} covers the addition of 8921 @ref{6d,,gcc_jit_context_set_bool_use_external_driver()} 8922 8923 @node LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_5,ABI symbol tags 8924 @anchor{topics/compatibility id7}@anchor{146}@anchor{topics/compatibility libgccjit-abi-6}@anchor{db} 8925 @subsubsection @code{LIBGCCJIT_ABI_6} 8926 8927 8928 @code{LIBGCCJIT_ABI_6} covers the addition of 8929 @ref{da,,gcc_jit_rvalue_set_bool_require_tail_call()} 8930 8931 @node LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_6,ABI symbol tags 8932 @anchor{topics/compatibility id8}@anchor{147}@anchor{topics/compatibility libgccjit-abi-7}@anchor{85} 8933 @subsubsection @code{LIBGCCJIT_ABI_7} 8934 8935 8936 @code{LIBGCCJIT_ABI_7} covers the addition of 8937 @ref{84,,gcc_jit_type_get_aligned()} 8938 8939 @node LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_7,ABI symbol tags 8940 @anchor{topics/compatibility id9}@anchor{148}@anchor{topics/compatibility libgccjit-abi-8}@anchor{88} 8941 @subsubsection @code{LIBGCCJIT_ABI_8} 8942 8943 8944 @code{LIBGCCJIT_ABI_8} covers the addition of 8945 @ref{87,,gcc_jit_type_get_vector()} 8946 8947 @node LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_8,ABI symbol tags 8948 @anchor{topics/compatibility id10}@anchor{149}@anchor{topics/compatibility libgccjit-abi-9}@anchor{123} 8949 @subsubsection @code{LIBGCCJIT_ABI_9} 8950 8951 8952 @code{LIBGCCJIT_ABI_9} covers the addition of 8953 @ref{dd,,gcc_jit_function_get_address()} 8954 8955 @node LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_9,ABI symbol tags 8956 @anchor{topics/compatibility id11}@anchor{14a}@anchor{topics/compatibility libgccjit-abi-10}@anchor{bd} 8957 @subsubsection @code{LIBGCCJIT_ABI_10} 8958 8959 8960 @code{LIBGCCJIT_ABI_10} covers the addition of 8961 @ref{89,,gcc_jit_context_new_rvalue_from_vector()} 8962 8963 @node LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_10,ABI symbol tags 8964 @anchor{topics/compatibility id12}@anchor{14b}@anchor{topics/compatibility libgccjit-abi-11}@anchor{77} 8965 @subsubsection @code{LIBGCCJIT_ABI_11} 8966 8967 8968 @code{LIBGCCJIT_ABI_11} covers the addition of 8969 @ref{76,,gcc_jit_context_add_driver_option()} 8970 8971 @node LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_11,ABI symbol tags 8972 @anchor{topics/compatibility id13}@anchor{14c}@anchor{topics/compatibility libgccjit-abi-12}@anchor{8f} 8973 @subsubsection @code{LIBGCCJIT_ABI_12} 8974 8975 8976 @code{LIBGCCJIT_ABI_12} covers the addition of 8977 @ref{8e,,gcc_jit_context_new_bitfield()} 8978 8979 @node LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_12,ABI symbol tags 8980 @anchor{topics/compatibility id14}@anchor{14d}@anchor{topics/compatibility libgccjit-abi-13}@anchor{14e} 8981 @subsubsection @code{LIBGCCJIT_ABI_13} 8982 8983 8984 @code{LIBGCCJIT_ABI_13} covers the addition of version functions via API 8985 entrypoints: 8986 8987 @quotation 8988 8989 8990 @itemize * 8991 8992 @item 8993 @ref{133,,gcc_jit_version_major()} 8994 8995 @item 8996 @ref{134,,gcc_jit_version_minor()} 8997 8998 @item 8999 @ref{135,,gcc_jit_version_patchlevel()} 9000 @end itemize 9001 @end quotation 9002 9003 @node LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_15,LIBGCCJIT_ABI_13,ABI symbol tags 9004 @anchor{topics/compatibility id15}@anchor{14f}@anchor{topics/compatibility libgccjit-abi-14}@anchor{fc} 9005 @subsubsection @code{LIBGCCJIT_ABI_14} 9006 9007 9008 @code{LIBGCCJIT_ABI_14} covers the addition of 9009 @ref{fb,,gcc_jit_global_set_initializer()} 9010 9011 @node LIBGCCJIT_ABI_15,LIBGCCJIT_ABI_16,LIBGCCJIT_ABI_14,ABI symbol tags 9012 @anchor{topics/compatibility id16}@anchor{150}@anchor{topics/compatibility libgccjit-abi-15}@anchor{151} 9013 @subsubsection @code{LIBGCCJIT_ABI_15} 9014 9015 9016 @code{LIBGCCJIT_ABI_15} covers the addition of API entrypoints for directly 9017 embedding assembler instructions: 9018 9019 @quotation 9020 9021 9022 @itemize * 9023 9024 @item 9025 @ref{152,,gcc_jit_block_add_extended_asm()} 9026 9027 @item 9028 @ref{153,,gcc_jit_block_end_with_extended_asm_goto()} 9029 9030 @item 9031 @ref{154,,gcc_jit_extended_asm_as_object()} 9032 9033 @item 9034 @ref{155,,gcc_jit_extended_asm_set_volatile_flag()} 9035 9036 @item 9037 @ref{156,,gcc_jit_extended_asm_set_inline_flag()} 9038 9039 @item 9040 @ref{157,,gcc_jit_extended_asm_add_output_operand()} 9041 9042 @item 9043 @ref{158,,gcc_jit_extended_asm_add_input_operand()} 9044 9045 @item 9046 @ref{159,,gcc_jit_extended_asm_add_clobber()} 9047 9048 @item 9049 @ref{15a,,gcc_jit_context_add_top_level_asm()} 9050 @end itemize 9051 @end quotation 9052 9053 @node LIBGCCJIT_ABI_16,LIBGCCJIT_ABI_17,LIBGCCJIT_ABI_15,ABI symbol tags 9054 @anchor{topics/compatibility id17}@anchor{15b}@anchor{topics/compatibility libgccjit-abi-16}@anchor{a8} 9055 @subsubsection @code{LIBGCCJIT_ABI_16} 9056 9057 9058 @code{LIBGCCJIT_ABI_16} covers the addition of reflection functions via API 9059 entrypoints: 9060 9061 @quotation 9062 9063 9064 @itemize * 9065 9066 @item 9067 @ref{112,,gcc_jit_function_get_return_type()} 9068 9069 @item 9070 @ref{111,,gcc_jit_function_get_param_count()} 9071 9072 @item 9073 @ref{99,,gcc_jit_type_dyncast_array()} 9074 9075 @item 9076 @ref{9a,,gcc_jit_type_is_bool()} 9077 9078 @item 9079 @ref{9f,,gcc_jit_type_is_integral()} 9080 9081 @item 9082 @ref{a0,,gcc_jit_type_is_pointer()} 9083 9084 @item 9085 @ref{a2,,gcc_jit_type_is_struct()} 9086 9087 @item 9088 @ref{a1,,gcc_jit_type_dyncast_vector()} 9089 9090 @item 9091 @ref{a5,,gcc_jit_type_unqualified()} 9092 9093 @item 9094 @ref{9b,,gcc_jit_type_dyncast_function_ptr_type()} 9095 9096 @item 9097 @ref{9c,,gcc_jit_function_type_get_return_type()} 9098 9099 @item 9100 @ref{9d,,gcc_jit_function_type_get_param_count()} 9101 9102 @item 9103 @ref{9e,,gcc_jit_function_type_get_param_type()} 9104 9105 @item 9106 @ref{a3,,gcc_jit_vector_type_get_num_units()} 9107 9108 @item 9109 @ref{a4,,gcc_jit_vector_type_get_element_type()} 9110 9111 @item 9112 @ref{a6,,gcc_jit_struct_get_field()} 9113 9114 @item 9115 @ref{a7,,gcc_jit_struct_get_field_count()} 9116 @end itemize 9117 @end quotation 9118 9119 @node LIBGCCJIT_ABI_17,LIBGCCJIT_ABI_18,LIBGCCJIT_ABI_16,ABI symbol tags 9120 @anchor{topics/compatibility id18}@anchor{15c}@anchor{topics/compatibility libgccjit-abi-17}@anchor{ed} 9121 @subsubsection @code{LIBGCCJIT_ABI_17} 9122 9123 9124 @code{LIBGCCJIT_ABI_17} covers the addition of an API entrypoint to set the 9125 thread-local storage model of a variable: 9126 9127 @quotation 9128 9129 9130 @itemize * 9131 9132 @item 9133 @ref{e6,,gcc_jit_lvalue_set_tls_model()} 9134 @end itemize 9135 @end quotation 9136 9137 @node LIBGCCJIT_ABI_18,LIBGCCJIT_ABI_19,LIBGCCJIT_ABI_17,ABI symbol tags 9138 @anchor{topics/compatibility id19}@anchor{15d}@anchor{topics/compatibility libgccjit-abi-18}@anchor{ef} 9139 @subsubsection @code{LIBGCCJIT_ABI_18} 9140 9141 9142 @code{LIBGCCJIT_ABI_18} covers the addition of an API entrypoint to set the link 9143 section of a variable: 9144 9145 @quotation 9146 9147 9148 @itemize * 9149 9150 @item 9151 @ref{ee,,gcc_jit_lvalue_set_link_section()} 9152 @end itemize 9153 @end quotation 9154 9155 @node LIBGCCJIT_ABI_19,LIBGCCJIT_ABI_20,LIBGCCJIT_ABI_18,ABI symbol tags 9156 @anchor{topics/compatibility id20}@anchor{15e}@anchor{topics/compatibility libgccjit-abi-19}@anchor{b8} 9157 @subsubsection @code{LIBGCCJIT_ABI_19} 9158 9159 9160 @code{LIBGCCJIT_ABI_19} covers the addition of API entrypoints to set the initial value 9161 of a global with an rvalue and to use constructors: 9162 9163 @quotation 9164 9165 9166 @itemize * 9167 9168 @item 9169 @ref{b9,,gcc_jit_context_new_array_constructor()} 9170 9171 @item 9172 @ref{ba,,gcc_jit_context_new_struct_constructor()} 9173 9174 @item 9175 @ref{bb,,gcc_jit_context_new_union_constructor()} 9176 9177 @item 9178 @ref{b7,,gcc_jit_global_set_initializer_rvalue()} 9179 @end itemize 9180 @end quotation 9181 9182 @node LIBGCCJIT_ABI_20,LIBGCCJIT_ABI_21,LIBGCCJIT_ABI_19,ABI symbol tags 9183 @anchor{topics/compatibility id21}@anchor{15f}@anchor{topics/compatibility libgccjit-abi-20}@anchor{ab} 9184 @subsubsection @code{LIBGCCJIT_ABI_20} 9185 9186 9187 @code{LIBGCCJIT_ABI_20} covers the addition of sized integer types, including 9188 128-bit integers and helper functions for types: 9189 9190 @quotation 9191 9192 9193 @itemize * 9194 9195 @item 9196 @ref{aa,,gcc_jit_compatible_types()} 9197 9198 @item 9199 @ref{ac,,gcc_jit_type_get_size()} 9200 9201 @item 9202 @code{GCC_JIT_TYPE_UINT8_T} 9203 9204 @item 9205 @code{GCC_JIT_TYPE_UINT16_T} 9206 9207 @item 9208 @code{GCC_JIT_TYPE_UINT32_T} 9209 9210 @item 9211 @code{GCC_JIT_TYPE_UINT64_T} 9212 9213 @item 9214 @code{GCC_JIT_TYPE_UINT128_T} 9215 9216 @item 9217 @code{GCC_JIT_TYPE_INT8_T} 9218 9219 @item 9220 @code{GCC_JIT_TYPE_INT16_T} 9221 9222 @item 9223 @code{GCC_JIT_TYPE_INT32_T} 9224 9225 @item 9226 @code{GCC_JIT_TYPE_INT64_T} 9227 9228 @item 9229 @code{GCC_JIT_TYPE_INT128_T} 9230 @end itemize 9231 @end quotation 9232 9233 @node LIBGCCJIT_ABI_21,LIBGCCJIT_ABI_22,LIBGCCJIT_ABI_20,ABI symbol tags 9234 @anchor{topics/compatibility id22}@anchor{160}@anchor{topics/compatibility libgccjit-abi-21}@anchor{e1} 9235 @subsubsection @code{LIBGCCJIT_ABI_21} 9236 9237 9238 @code{LIBGCCJIT_ABI_21} covers the addition of an API entrypoint to bitcast a 9239 value from one type to another: 9240 9241 @quotation 9242 9243 9244 @itemize * 9245 9246 @item 9247 @ref{e0,,gcc_jit_context_new_bitcast()} 9248 @end itemize 9249 @end quotation 9250 9251 @node LIBGCCJIT_ABI_22,LIBGCCJIT_ABI_23,LIBGCCJIT_ABI_21,ABI symbol tags 9252 @anchor{topics/compatibility id23}@anchor{161}@anchor{topics/compatibility libgccjit-abi-22}@anchor{f0} 9253 @subsubsection @code{LIBGCCJIT_ABI_22} 9254 9255 9256 @code{LIBGCCJIT_ABI_22} covers the addition of an API entrypoint to set the 9257 register name of a variable: 9258 9259 @quotation 9260 9261 9262 @itemize * 9263 9264 @item 9265 @code{gcc_jit_lvalue_set_register_name()} 9266 @end itemize 9267 @end quotation 9268 9269 @node LIBGCCJIT_ABI_23,LIBGCCJIT_ABI_24,LIBGCCJIT_ABI_22,ABI symbol tags 9270 @anchor{topics/compatibility id24}@anchor{162}@anchor{topics/compatibility libgccjit-abi-23}@anchor{70} 9271 @subsubsection @code{LIBGCCJIT_ABI_23} 9272 9273 9274 @code{LIBGCCJIT_ABI_23} covers the addition of an API entrypoint to hide stderr 9275 logs: 9276 9277 @quotation 9278 9279 9280 @itemize * 9281 9282 @item 9283 @ref{6f,,gcc_jit_context_set_bool_print_errors_to_stderr()} 9284 @end itemize 9285 @end quotation 9286 9287 @node LIBGCCJIT_ABI_24,,LIBGCCJIT_ABI_23,ABI symbol tags 9288 @anchor{topics/compatibility id25}@anchor{163}@anchor{topics/compatibility libgccjit-abi-24}@anchor{f2} 9289 @subsubsection @code{LIBGCCJIT_ABI_24} 9290 9291 9292 @code{LIBGCCJIT_ABI_24} covers the addition of functions to get and set the 9293 alignment of a variable: 9294 9295 @quotation 9296 9297 9298 @itemize * 9299 9300 @item 9301 @ref{f1,,gcc_jit_lvalue_set_alignment()} 9302 9303 @item 9304 @ref{f3,,gcc_jit_lvalue_get_alignment()} 9305 @end itemize 9306 @end quotation 9307 9308 @c Copyright (C) 2015-2022 Free Software Foundation, Inc. 9309 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 9310 @c 9311 @c This is free software: you can redistribute it and/or modify it 9312 @c under the terms of the GNU General Public License as published by 9313 @c the Free Software Foundation, either version 3 of the License, or 9314 @c (at your option) any later version. 9315 @c 9316 @c This program is distributed in the hope that it will be useful, but 9317 @c WITHOUT ANY WARRANTY; without even the implied warranty of 9318 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9319 @c General Public License for more details. 9320 @c 9321 @c You should have received a copy of the GNU General Public License 9322 @c along with this program. If not, see 9323 @c <https://www.gnu.org/licenses/>. 9324 9325 @node Performance,Using Assembly Language with libgccjit,ABI and API compatibility,Topic Reference 9326 @anchor{topics/performance doc}@anchor{164}@anchor{topics/performance performance}@anchor{165} 9327 @section Performance 9328 9329 9330 @menu 9331 * The timing API:: 9332 9333 @end menu 9334 9335 @node The timing API,,,Performance 9336 @anchor{topics/performance the-timing-api}@anchor{166} 9337 @subsection The timing API 9338 9339 9340 As of GCC 6, libgccjit exposes a timing API, for printing reports on 9341 how long was spent in different parts of code. 9342 9343 You can create a @ref{167,,gcc_jit_timer} instance, which will 9344 measure time spent since its creation. The timer maintains a stack 9345 of timer items: as control flow moves through your code, you can push 9346 and pop named items relating to your code onto the stack, and the timer 9347 will account the time spent accordingly. 9348 9349 You can also asssociate a timer with a @ref{8,,gcc_jit_context}, in 9350 which case the time spent inside compilation will be subdivided. 9351 9352 For example, the following code uses a timer, recording client items 9353 create_code, compile, and running code: 9354 9355 @example 9356 /* Create a timer. */ 9357 gcc_jit_timer *timer = gcc_jit_timer_new (); 9358 if (!timer) 9359 @{ 9360 error ("gcc_jit_timer_new failed"); 9361 return -1; 9362 @} 9363 9364 /* Let's repeatedly compile and run some code, accumulating it 9365 all into the timer. */ 9366 for (int i = 0; i < num_iterations; i++) 9367 @{ 9368 /* Create a context and associate it with the timer. */ 9369 gcc_jit_context *ctxt = gcc_jit_context_acquire (); 9370 if (!ctxt) 9371 @{ 9372 error ("gcc_jit_context_acquire failed"); 9373 return -1; 9374 @} 9375 gcc_jit_context_set_timer (ctxt, timer); 9376 9377 /* Populate the context, timing it as client item "create_code". */ 9378 gcc_jit_timer_push (timer, "create_code"); 9379 create_code (ctxt); 9380 gcc_jit_timer_pop (timer, "create_code"); 9381 9382 /* Compile the context, timing it as client item "compile". */ 9383 gcc_jit_timer_push (timer, "compile"); 9384 result = gcc_jit_context_compile (ctxt); 9385 gcc_jit_timer_pop (timer, "compile"); 9386 9387 /* Run the generated code, timing it as client item "running code". */ 9388 gcc_jit_timer_push (timer, "running code"); 9389 run_the_code (ctxt, result); 9390 gcc_jit_timer_pop (timer, "running code"); 9391 9392 /* Clean up. */ 9393 gcc_jit_context_release (ctxt); 9394 gcc_jit_result_release (result); 9395 @} 9396 9397 /* Print the accumulated timings. */ 9398 gcc_jit_timer_print (timer, stderr); 9399 gcc_jit_timer_release (timer); 9400 @end example 9401 9402 giving output like this, showing the internal GCC items at the top, then 9403 client items, then the total: 9404 9405 @example 9406 Execution times (seconds) 9407 GCC items: 9408 phase setup : 0.29 (14%) usr 0.00 ( 0%) sys 0.32 ( 5%) wall 10661 kB (50%) ggc 9409 phase parsing : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 653 kB ( 3%) ggc 9410 phase finalize : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9411 dump files : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 9412 callgraph construction : 0.02 ( 1%) usr 0.01 ( 6%) sys 0.01 ( 0%) wall 242 kB ( 1%) ggc 9413 callgraph optimization : 0.03 ( 2%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 142 kB ( 1%) ggc 9414 trivially dead code : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9415 df scan insns : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 9 kB ( 0%) ggc 9416 df live regs : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 9417 inline parameters : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 82 kB ( 0%) ggc 9418 tree CFG cleanup : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9419 tree PHI insertion : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 64 kB ( 0%) ggc 9420 tree SSA other : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 18 kB ( 0%) ggc 9421 expand : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 398 kB ( 2%) ggc 9422 jump : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9423 loop init : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 67 kB ( 0%) ggc 9424 integrated RA : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 2468 kB (12%) ggc 9425 thread pro- & epilogue : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 162 kB ( 1%) ggc 9426 final : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 216 kB ( 1%) ggc 9427 rest of compilation : 1.37 (69%) usr 0.00 ( 0%) sys 1.13 (18%) wall 1391 kB ( 6%) ggc 9428 assemble JIT code : 0.01 ( 1%) usr 0.00 ( 0%) sys 4.04 (66%) wall 0 kB ( 0%) ggc 9429 load JIT result : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9430 JIT client code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9431 Client items: 9432 create_code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9433 compile : 0.36 (18%) usr 0.15 (83%) sys 0.86 (14%) wall 14939 kB (70%) ggc 9434 running code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 9435 TOTAL : 2.00 0.18 6.12 21444 kB 9436 @end example 9437 9438 The exact format is intended to be human-readable, and is subject to change. 9439 9440 @geindex LIBGCCJIT_HAVE_TIMING_API (C macro) 9441 @anchor{topics/performance c LIBGCCJIT_HAVE_TIMING_API}@anchor{168} 9442 @deffn {C Macro} LIBGCCJIT_HAVE_TIMING_API 9443 9444 The timer API was added to libgccjit in GCC 6. 9445 This macro is only defined in versions of libgccjit.h which have the 9446 timer API, and so can be used to guard code that may need to compile 9447 against earlier releases: 9448 9449 @example 9450 #ifdef LIBGCCJIT_HAVE_TIMING_API 9451 gcc_jit_timer *t = gcc_jit_timer_new (); 9452 gcc_jit_context_set_timer (ctxt, t); 9453 #endif 9454 @end example 9455 @end deffn 9456 9457 @geindex gcc_jit_timer (C type) 9458 @anchor{topics/performance c gcc_jit_timer}@anchor{167} 9459 @deffn {C Type} gcc_jit_timer 9460 @end deffn 9461 9462 @geindex gcc_jit_timer_new (C function) 9463 @anchor{topics/performance c gcc_jit_timer_new}@anchor{140} 9464 @deffn {C Function} gcc_jit_timer * gcc_jit_timer_new (void) 9465 9466 Create a @ref{167,,gcc_jit_timer} instance, and start timing: 9467 9468 @example 9469 gcc_jit_timer *t = gcc_jit_timer_new (); 9470 @end example 9471 9472 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9473 for its presence using 9474 9475 @example 9476 #ifdef LIBGCCJIT_HAVE_TIMING_API 9477 @end example 9478 @end deffn 9479 9480 @geindex gcc_jit_timer_release (C function) 9481 @anchor{topics/performance c gcc_jit_timer_release}@anchor{141} 9482 @deffn {C Function} void gcc_jit_timer_release (gcc_jit_timer@w{ }*timer) 9483 9484 Release a @ref{167,,gcc_jit_timer} instance: 9485 9486 @example 9487 gcc_jit_timer_release (t); 9488 @end example 9489 9490 This should be called exactly once on a timer. 9491 9492 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9493 for its presence using 9494 9495 @example 9496 #ifdef LIBGCCJIT_HAVE_TIMING_API 9497 @end example 9498 @end deffn 9499 9500 @geindex gcc_jit_context_set_timer (C function) 9501 @anchor{topics/performance c gcc_jit_context_set_timer}@anchor{13f} 9502 @deffn {C Function} void gcc_jit_context_set_timer (gcc_jit_context@w{ }*ctxt, gcc_jit_timer@w{ }*timer) 9503 9504 Associate a @ref{167,,gcc_jit_timer} instance with a context: 9505 9506 @example 9507 gcc_jit_context_set_timer (ctxt, t); 9508 @end example 9509 9510 A timer instance can be shared between multiple 9511 @ref{8,,gcc_jit_context} instances. 9512 9513 Timers have no locking, so if you have a multithreaded program, you 9514 must provide your own locks if more than one thread could be working 9515 with the same timer via timer-associated contexts. 9516 9517 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9518 for its presence using 9519 9520 @example 9521 #ifdef LIBGCCJIT_HAVE_TIMING_API 9522 @end example 9523 @end deffn 9524 9525 @geindex gcc_jit_context_get_timer (C function) 9526 @anchor{topics/performance c gcc_jit_context_get_timer}@anchor{13e} 9527 @deffn {C Function} gcc_jit_timer *gcc_jit_context_get_timer (gcc_jit_context@w{ }*ctxt) 9528 9529 Get the timer associated with a context (if any). 9530 9531 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9532 for its presence using 9533 9534 @example 9535 #ifdef LIBGCCJIT_HAVE_TIMING_API 9536 @end example 9537 @end deffn 9538 9539 @geindex gcc_jit_timer_push (C function) 9540 @anchor{topics/performance c gcc_jit_timer_push}@anchor{142} 9541 @deffn {C Function} void gcc_jit_timer_push (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name) 9542 9543 Push the given item onto the timers stack: 9544 9545 @example 9546 gcc_jit_timer_push (t, "running code"); 9547 run_the_code (ctxt, result); 9548 gcc_jit_timer_pop (t, "running code"); 9549 @end example 9550 9551 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9552 for its presence using 9553 9554 @example 9555 #ifdef LIBGCCJIT_HAVE_TIMING_API 9556 @end example 9557 @end deffn 9558 9559 @geindex gcc_jit_timer_pop (C function) 9560 @anchor{topics/performance c gcc_jit_timer_pop}@anchor{143} 9561 @deffn {C Function} void gcc_jit_timer_pop (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name) 9562 9563 Pop the top item from the timers stack. 9564 9565 If item_name is provided, it must match that of the top item. 9566 Alternatively, @code{NULL} can be passed in, to suppress checking. 9567 9568 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9569 for its presence using 9570 9571 @example 9572 #ifdef LIBGCCJIT_HAVE_TIMING_API 9573 @end example 9574 @end deffn 9575 9576 @geindex gcc_jit_timer_print (C function) 9577 @anchor{topics/performance c gcc_jit_timer_print}@anchor{144} 9578 @deffn {C Function} void gcc_jit_timer_print (gcc_jit_timer@w{ }*timer, FILE@w{ }*f_out) 9579 9580 Print timing information to the given stream about activity since 9581 the timer was started. 9582 9583 This API entrypoint was added in @ref{13d,,LIBGCCJIT_ABI_4}; you can test 9584 for its presence using 9585 9586 @example 9587 #ifdef LIBGCCJIT_HAVE_TIMING_API 9588 @end example 9589 @end deffn 9590 9591 @c Copyright (C) 2020-2022 Free Software Foundation, Inc. 9592 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 9593 @c 9594 @c This is free software: you can redistribute it and/or modify it 9595 @c under the terms of the GNU General Public License as published by 9596 @c the Free Software Foundation, either version 3 of the License, or 9597 @c (at your option) any later version. 9598 @c 9599 @c This program is distributed in the hope that it will be useful, but 9600 @c WITHOUT ANY WARRANTY; without even the implied warranty of 9601 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9602 @c General Public License for more details. 9603 @c 9604 @c You should have received a copy of the GNU General Public License 9605 @c along with this program. If not, see 9606 @c <https://www.gnu.org/licenses/>. 9607 9608 @node Using Assembly Language with libgccjit,,Performance,Topic Reference 9609 @anchor{topics/asm doc}@anchor{169}@anchor{topics/asm using-assembly-language-with-libgccjit}@anchor{16a} 9610 @section Using Assembly Language with libgccjit 9611 9612 9613 libgccjit has some support for directly embedding assembler instructions. 9614 This is based on GCCs support for inline @code{asm} in C code, and the 9615 following assumes a familiarity with that functionality. See 9616 How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html} 9617 in GCCs documentation, the Extended Asm section in particular. 9618 9619 These entrypoints were added in @ref{151,,LIBGCCJIT_ABI_15}; you can test 9620 for their presence using 9621 9622 @quotation 9623 9624 @example 9625 #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS 9626 @end example 9627 @end quotation 9628 9629 @menu 9630 * Adding assembler instructions within a function:: 9631 * Adding top-level assembler statements:: 9632 9633 @end menu 9634 9635 @node Adding assembler instructions within a function,Adding top-level assembler statements,,Using Assembly Language with libgccjit 9636 @anchor{topics/asm adding-assembler-instructions-within-a-function}@anchor{16b} 9637 @subsection Adding assembler instructions within a function 9638 9639 9640 @geindex gcc_jit_extended_asm (C type) 9641 @anchor{topics/asm c gcc_jit_extended_asm}@anchor{120} 9642 @deffn {C Type} gcc_jit_extended_asm 9643 9644 A @cite{gcc_jit_extended_asm} represents an extended @code{asm} statement: a 9645 series of low-level instructions inside a function that convert inputs 9646 to outputs. 9647 9648 To avoid having an API entrypoint with a very large number of 9649 parameters, an extended @code{asm} statement is made in stages: 9650 an initial call to create the @ref{120,,gcc_jit_extended_asm}, 9651 followed by calls to add operands and set other properties of the 9652 statement. 9653 9654 There are two API entrypoints for creating a @ref{120,,gcc_jit_extended_asm}: 9655 9656 9657 @itemize * 9658 9659 @item 9660 @ref{152,,gcc_jit_block_add_extended_asm()} for an @code{asm} statement with 9661 no control flow, and 9662 9663 @item 9664 @ref{153,,gcc_jit_block_end_with_extended_asm_goto()} for an @code{asm goto}. 9665 @end itemize 9666 9667 For example, to create the equivalent of: 9668 9669 @example 9670 asm ("mov %1, %0\n\t" 9671 "add $1, %0" 9672 : "=r" (dst) 9673 : "r" (src)); 9674 @end example 9675 9676 the following API calls could be used: 9677 9678 @example 9679 gcc_jit_extended_asm *ext_asm 9680 = gcc_jit_block_add_extended_asm (block, NULL, 9681 "mov %1, %0\n\t" 9682 "add $1, %0"); 9683 gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst); 9684 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 9685 gcc_jit_lvalue_as_rvalue (src)); 9686 @end example 9687 9688 @cartouche 9689 @quotation Warning 9690 When considering the numbering of operands within an 9691 extended @code{asm} statement (e.g. the @code{%0} and @code{%1} 9692 above), the equivalent to the C syntax is followed i.e. all 9693 output operands, then all input operands, regardless of 9694 what order the calls to 9695 @ref{157,,gcc_jit_extended_asm_add_output_operand()} and 9696 @ref{158,,gcc_jit_extended_asm_add_input_operand()} were made in. 9697 @end quotation 9698 @end cartouche 9699 9700 As in the C syntax, operands can be given symbolic names to avoid having 9701 to number them. For example, to create the equivalent of: 9702 9703 @example 9704 asm ("bsfl %[aMask], %[aIndex]" 9705 : [aIndex] "=r" (Index) 9706 : [aMask] "r" (Mask) 9707 : "cc"); 9708 @end example 9709 9710 the following API calls could be used: 9711 9712 @example 9713 gcc_jit_extended_asm *ext_asm 9714 = gcc_jit_block_add_extended_asm (block, NULL, 9715 "bsfl %[aMask], %[aIndex]"); 9716 gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index); 9717 gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r", 9718 gcc_jit_param_as_rvalue (mask)); 9719 gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 9720 @end example 9721 @end deffn 9722 9723 @geindex gcc_jit_block_add_extended_asm (C function) 9724 @anchor{topics/asm c gcc_jit_block_add_extended_asm}@anchor{152} 9725 @deffn {C Function} gcc_jit_extended_asm * gcc_jit_block_add_extended_asm (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*asm_template) 9726 9727 Create a @ref{120,,gcc_jit_extended_asm} for an extended @code{asm} statement 9728 with no control flow (i.e. without the @code{goto} qualifier). 9729 9730 The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate} 9731 within Cs extended @code{asm} syntax. It must be non-NULL. The call takes 9732 a copy of the underlying string, so it is valid to pass in a pointer to 9733 an on-stack buffer. 9734 @end deffn 9735 9736 @geindex gcc_jit_block_end_with_extended_asm_goto (C function) 9737 @anchor{topics/asm c gcc_jit_block_end_with_extended_asm_goto}@anchor{153} 9738 @deffn {C Function} gcc_jit_extended_asm * gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*asm_template, int@w{ }num_goto_blocks, gcc_jit_block@w{ }**goto_blocks, gcc_jit_block@w{ }*fallthrough_block) 9739 9740 Create a @ref{120,,gcc_jit_extended_asm} for an extended @code{asm} statement 9741 that may perform jumps, and use it to terminate the given block. 9742 This is equivalent to the @code{goto} qualifier in Cs extended @code{asm} 9743 syntax. 9744 9745 For example, to create the equivalent of: 9746 9747 @example 9748 asm goto ("btl %1, %0\n\t" 9749 "jc %l[carry]" 9750 : // No outputs 9751 : "r" (p1), "r" (p2) 9752 : "cc" 9753 : carry); 9754 @end example 9755 9756 the following API calls could be used: 9757 9758 @example 9759 const char *asm_template = 9760 (use_name 9761 ? /* Label referred to by name: "%l[carry]". */ 9762 ("btl %1, %0\n\t" 9763 "jc %l[carry]") 9764 : /* Label referred to numerically: "%l2". */ 9765 ("btl %1, %0\n\t" 9766 "jc %l2")); 9767 9768 gcc_jit_extended_asm *ext_asm 9769 = gcc_jit_block_end_with_extended_asm_goto (b_start, NULL, 9770 asm_template, 9771 1, &b_carry, 9772 b_fallthru); 9773 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 9774 gcc_jit_param_as_rvalue (p1)); 9775 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 9776 gcc_jit_param_as_rvalue (p2)); 9777 gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 9778 @end example 9779 9780 here referencing a @ref{28,,gcc_jit_block} named carry. 9781 9782 @code{num_goto_blocks} must be >= 0. 9783 9784 @code{goto_blocks} must be non-NULL. This corresponds to the @code{GotoLabels} 9785 parameter within Cs extended @code{asm} syntax. The block names can be 9786 referenced within the assembler template. 9787 9788 @code{fallthrough_block} can be NULL. If non-NULL, it specifies the block 9789 to fall through to after the statement. 9790 9791 @cartouche 9792 @quotation Note 9793 This is needed since each @ref{28,,gcc_jit_block} must have a 9794 single exit point, as a basic block: you cant jump from the 9795 middle of a block. A goto is implicitly added after the 9796 asm to handle the fallthrough case, which is equivalent to what 9797 would have happened in the C case. 9798 @end quotation 9799 @end cartouche 9800 @end deffn 9801 9802 @geindex gcc_jit_extended_asm_set_volatile_flag (C function) 9803 @anchor{topics/asm c gcc_jit_extended_asm_set_volatile_flag}@anchor{155} 9804 @deffn {C Function} void gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag) 9805 9806 Set whether the @ref{120,,gcc_jit_extended_asm} has side-effects, equivalent to the 9807 volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile} 9808 qualifier in Cs extended asm syntax. 9809 9810 For example, to create the equivalent of: 9811 9812 @example 9813 asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX. 9814 "shl $32, %%rdx\n\t" // Shift the upper bits left. 9815 "or %%rdx, %0" // 'Or' in the lower bits. 9816 : "=a" (msr) 9817 : 9818 : "rdx"); 9819 @end example 9820 9821 the following API calls could be used: 9822 9823 @example 9824 gcc_jit_extended_asm *ext_asm 9825 = gcc_jit_block_add_extended_asm 9826 (block, NULL, 9827 "rdtsc\n\t" /* Returns the time in EDX:EAX. */ 9828 "shl $32, %%rdx\n\t" /* Shift the upper bits left. */ 9829 "or %%rdx, %0"); /* 'Or' in the lower bits. */ 9830 gcc_jit_extended_asm_set_volatile_flag (ext_asm, 1); 9831 gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=a", msr); 9832 gcc_jit_extended_asm_add_clobber (ext_asm, "rdx"); 9833 @end example 9834 9835 where the @ref{120,,gcc_jit_extended_asm} is flagged as volatile. 9836 @end deffn 9837 9838 @geindex gcc_jit_extended_asm_set_inline_flag (C function) 9839 @anchor{topics/asm c gcc_jit_extended_asm_set_inline_flag}@anchor{156} 9840 @deffn {C Function} void gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag) 9841 9842 Set the equivalent of the 9843 inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm} 9844 qualifier in Cs extended @code{asm} syntax. 9845 @end deffn 9846 9847 @geindex gcc_jit_extended_asm_add_output_operand (C function) 9848 @anchor{topics/asm c gcc_jit_extended_asm_add_output_operand}@anchor{157} 9849 @deffn {C Function} void gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*asm_symbolic_name, const char@w{ }*constraint, gcc_jit_lvalue@w{ }*dest) 9850 9851 Add an output operand to the extended @code{asm} statement. See the 9852 Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands} 9853 section of the documentation of the C syntax. 9854 9855 @code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of Cs 9856 extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the 9857 symbolic name for the operand. 9858 9859 @code{constraint} corresponds to the @code{constraint} component of Cs extended 9860 @code{asm} syntax. It must be non-NULL. 9861 9862 @code{dest} corresponds to the @code{cvariablename} component of Cs extended 9863 @code{asm} syntax. It must be non-NULL. 9864 9865 @example 9866 // Example with a NULL symbolic name, the equivalent of: 9867 // : "=r" (dst) 9868 gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst); 9869 9870 // Example with a symbolic name ("aIndex"), the equivalent of: 9871 // : [aIndex] "=r" (index) 9872 gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index); 9873 @end example 9874 9875 This function cant be called on an @code{asm goto} as such instructions cant 9876 have outputs; see the 9877 Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels} 9878 section of GCCs Extended Asm documentation. 9879 @end deffn 9880 9881 @geindex gcc_jit_extended_asm_add_input_operand (C function) 9882 @anchor{topics/asm c gcc_jit_extended_asm_add_input_operand}@anchor{158} 9883 @deffn {C Function} void gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*asm_symbolic_name, const char@w{ }*constraint, gcc_jit_rvalue@w{ }*src) 9884 9885 Add an input operand to the extended @code{asm} statement. See the 9886 Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands} 9887 section of the documentation of the C syntax. 9888 9889 @code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of Cs 9890 extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the 9891 symbolic name for the operand. 9892 9893 @code{constraint} corresponds to the @code{constraint} component of Cs extended 9894 @code{asm} syntax. It must be non-NULL. 9895 9896 @code{src} corresponds to the @code{cexpression} component of Cs extended 9897 @code{asm} syntax. It must be non-NULL. 9898 9899 @example 9900 // Example with a NULL symbolic name, the equivalent of: 9901 // : "r" (src) 9902 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 9903 gcc_jit_lvalue_as_rvalue (src)); 9904 9905 // Example with a symbolic name ("aMask"), the equivalent of: 9906 // : [aMask] "r" (Mask) 9907 gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r", 9908 gcc_jit_lvalue_as_rvalue (mask)); 9909 @end example 9910 @end deffn 9911 9912 @geindex gcc_jit_extended_asm_add_clobber (C function) 9913 @anchor{topics/asm c gcc_jit_extended_asm_add_clobber}@anchor{159} 9914 @deffn {C Function} void gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*victim) 9915 9916 Add @cite{victim} to the list of registers clobbered by the extended @code{asm} 9917 statement. It must be non-NULL. See the 9918 Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#} 9919 section of the documentation of the C syntax. 9920 9921 Statements with multiple clobbers will require multiple calls, one per 9922 clobber. 9923 9924 For example: 9925 9926 @example 9927 gcc_jit_extended_asm_add_clobber (ext_asm, "r0"); 9928 gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 9929 gcc_jit_extended_asm_add_clobber (ext_asm, "memory"); 9930 @end example 9931 @end deffn 9932 9933 A @ref{120,,gcc_jit_extended_asm} is a @ref{e,,gcc_jit_object} owned by 9934 the blocks context. The following upcast is available: 9935 9936 @geindex gcc_jit_extended_asm_as_object (C function) 9937 @anchor{topics/asm c gcc_jit_extended_asm_as_object}@anchor{154} 9938 @deffn {C Function} gcc_jit_object * gcc_jit_extended_asm_as_object (gcc_jit_extended_asm@w{ }*ext_asm) 9939 9940 Upcast from extended @code{asm} to object. 9941 @end deffn 9942 9943 @node Adding top-level assembler statements,,Adding assembler instructions within a function,Using Assembly Language with libgccjit 9944 @anchor{topics/asm adding-top-level-assembler-statements}@anchor{16c} 9945 @subsection Adding top-level assembler statements 9946 9947 9948 In addition to creating extended @code{asm} instructions within a function, 9949 there is support for creating top-level assembler statements, outside 9950 of any function. 9951 9952 @geindex gcc_jit_context_add_top_level_asm (C function) 9953 @anchor{topics/asm c gcc_jit_context_add_top_level_asm}@anchor{15a} 9954 @deffn {C Function} void gcc_jit_context_add_top_level_asm (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*asm_stmts) 9955 9956 Create a set of top-level asm statements, analogous to those created 9957 by GCCs basic @code{asm} syntax in C at file scope. 9958 9959 For example, to create the equivalent of: 9960 9961 @example 9962 asm ("\t.pushsection .text\n" 9963 "\t.globl add_asm\n" 9964 "\t.type add_asm, @@function\n" 9965 "add_asm:\n" 9966 "\tmovq %rdi, %rax\n" 9967 "\tadd %rsi, %rax\n" 9968 "\tret\n" 9969 "\t.popsection\n"); 9970 @end example 9971 9972 the following API calls could be used: 9973 9974 @example 9975 gcc_jit_context_add_top_level_asm (ctxt, NULL, 9976 "\t.pushsection .text\n" 9977 "\t.globl add_asm\n" 9978 "\t.type add_asm, @@function\n" 9979 "add_asm:\n" 9980 "\tmovq %rdi, %rax\n" 9981 "\tadd %rsi, %rax\n" 9982 "\tret\n" 9983 "\t# some asm here\n" 9984 "\t.popsection\n"); 9985 @end example 9986 @end deffn 9987 9988 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 9989 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 9990 @c 9991 @c This is free software: you can redistribute it and/or modify it 9992 @c under the terms of the GNU General Public License as published by 9993 @c the Free Software Foundation, either version 3 of the License, or 9994 @c (at your option) any later version. 9995 @c 9996 @c This program is distributed in the hope that it will be useful, but 9997 @c WITHOUT ANY WARRANTY; without even the implied warranty of 9998 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9999 @c General Public License for more details. 10000 @c 10001 @c You should have received a copy of the GNU General Public License 10002 @c along with this program. If not, see 10003 @c <https://www.gnu.org/licenses/>. 10004 10005 @node C++ bindings for libgccjit,Internals,Topic Reference,Top 10006 @anchor{cp/index doc}@anchor{16d}@anchor{cp/index c-bindings-for-libgccjit}@anchor{16e} 10007 @chapter C++ bindings for libgccjit 10008 10009 10010 This document describes the C++ bindings to 10011 libgccjit@footnote{https://gcc.gnu.org/wiki/JIT}, an API for embedding GCC 10012 inside programs and libraries. 10013 10014 The C++ bindings consist of a single header file @code{libgccjit++.h}. 10015 10016 This is a collection of thin wrapper classes around the C API. 10017 Everything is an inline function, implemented in terms of the C API, 10018 so there is nothing extra to link against. 10019 10020 Contents: 10021 10022 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 10023 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 10024 @c 10025 @c This is free software: you can redistribute it and/or modify it 10026 @c under the terms of the GNU General Public License as published by 10027 @c the Free Software Foundation, either version 3 of the License, or 10028 @c (at your option) any later version. 10029 @c 10030 @c This program is distributed in the hope that it will be useful, but 10031 @c WITHOUT ANY WARRANTY; without even the implied warranty of 10032 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10033 @c General Public License for more details. 10034 @c 10035 @c You should have received a copy of the GNU General Public License 10036 @c along with this program. If not, see 10037 @c <https://www.gnu.org/licenses/>. 10038 10039 @menu 10040 * Tutorial: Tutorial<2>. 10041 * Topic Reference: Topic Reference<2>. 10042 10043 @end menu 10044 10045 @node Tutorial<2>,Topic Reference<2>,,C++ bindings for libgccjit 10046 @anchor{cp/intro/index doc}@anchor{16f}@anchor{cp/intro/index tutorial}@anchor{170} 10047 @section Tutorial 10048 10049 10050 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 10051 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 10052 @c 10053 @c This is free software: you can redistribute it and/or modify it 10054 @c under the terms of the GNU General Public License as published by 10055 @c the Free Software Foundation, either version 3 of the License, or 10056 @c (at your option) any later version. 10057 @c 10058 @c This program is distributed in the hope that it will be useful, but 10059 @c WITHOUT ANY WARRANTY; without even the implied warranty of 10060 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10061 @c General Public License for more details. 10062 @c 10063 @c You should have received a copy of the GNU General Public License 10064 @c along with this program. If not, see 10065 @c <https://www.gnu.org/licenses/>. 10066 10067 @menu 10068 * Tutorial part 1; Hello world: Tutorial part 1 Hello world<2>. 10069 * Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>. 10070 * Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>. 10071 * Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>. 10072 10073 @end menu 10074 10075 @node Tutorial part 1 Hello world<2>,Tutorial part 2 Creating a trivial machine code function<2>,,Tutorial<2> 10076 @anchor{cp/intro/tutorial01 doc}@anchor{171}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{172} 10077 @subsection Tutorial part 1: Hello world 10078 10079 10080 Before we look at the details of the API, lets look at building and 10081 running programs that use the library. 10082 10083 Heres a toy hello world program that uses the librarys C++ API to 10084 synthesize a call to @cite{printf} and uses it to write a message to stdout. 10085 10086 Dont worry about the content of the program for now; well cover 10087 the details in later parts of this tutorial. 10088 10089 @quotation 10090 10091 @example 10092 /* Smoketest example for libgccjit.so C++ API 10093 Copyright (C) 2014-2022 Free Software Foundation, Inc. 10094 10095 This file is part of GCC. 10096 10097 GCC is free software; you can redistribute it and/or modify it 10098 under the terms of the GNU General Public License as published by 10099 the Free Software Foundation; either version 3, or (at your option) 10100 any later version. 10101 10102 GCC is distributed in the hope that it will be useful, but 10103 WITHOUT ANY WARRANTY; without even the implied warranty of 10104 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10105 General Public License for more details. 10106 10107 You should have received a copy of the GNU General Public License 10108 along with GCC; see the file COPYING3. If not see 10109 <http://www.gnu.org/licenses/>. */ 10110 10111 #include <libgccjit++.h> 10112 10113 #include <stdlib.h> 10114 #include <stdio.h> 10115 10116 static void 10117 create_code (gccjit::context ctxt) 10118 @{ 10119 /* Let's try to inject the equivalent of this C code: 10120 void 10121 greet (const char *name) 10122 @{ 10123 printf ("hello %s\n", name); 10124 @} 10125 */ 10126 gccjit::type void_type = ctxt.get_type (GCC_JIT_TYPE_VOID); 10127 gccjit::type const_char_ptr_type = 10128 ctxt.get_type (GCC_JIT_TYPE_CONST_CHAR_PTR); 10129 gccjit::param param_name = 10130 ctxt.new_param (const_char_ptr_type, "name"); 10131 std::vector<gccjit::param> func_params; 10132 func_params.push_back (param_name); 10133 gccjit::function func = 10134 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10135 void_type, 10136 "greet", 10137 func_params, 0); 10138 10139 gccjit::param param_format = 10140 ctxt.new_param (const_char_ptr_type, "format"); 10141 std::vector<gccjit::param> printf_params; 10142 printf_params.push_back (param_format); 10143 gccjit::function printf_func = 10144 ctxt.new_function (GCC_JIT_FUNCTION_IMPORTED, 10145 ctxt.get_type (GCC_JIT_TYPE_INT), 10146 "printf", 10147 printf_params, 1); 10148 10149 gccjit::block block = func.new_block (); 10150 block.add_eval (ctxt.new_call (printf_func, 10151 ctxt.new_rvalue ("hello %s\n"), 10152 param_name)); 10153 block.end_with_return (); 10154 @} 10155 10156 int 10157 main (int argc, char **argv) 10158 @{ 10159 gccjit::context ctxt; 10160 gcc_jit_result *result; 10161 10162 /* Get a "context" object for working with the library. */ 10163 ctxt = gccjit::context::acquire (); 10164 10165 /* Set some options on the context. 10166 Turn this on to see the code being generated, in assembler form. */ 10167 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 0); 10168 10169 /* Populate the context. */ 10170 create_code (ctxt); 10171 10172 /* Compile the code. */ 10173 result = ctxt.compile (); 10174 if (!result) 10175 @{ 10176 fprintf (stderr, "NULL result"); 10177 exit (1); 10178 @} 10179 10180 ctxt.release (); 10181 10182 /* Extract the generated code from "result". */ 10183 typedef void (*fn_type) (const char *); 10184 fn_type greet = 10185 (fn_type)gcc_jit_result_get_code (result, "greet"); 10186 if (!greet) 10187 @{ 10188 fprintf (stderr, "NULL greet"); 10189 exit (1); 10190 @} 10191 10192 /* Now call the generated function: */ 10193 greet ("world"); 10194 fflush (stdout); 10195 10196 gcc_jit_result_release (result); 10197 return 0; 10198 @} 10199 @end example 10200 @end quotation 10201 10202 Copy the above to @cite{tut01-hello-world.cc}. 10203 10204 Assuming you have the jit library installed, build the test program 10205 using: 10206 10207 @example 10208 $ gcc \ 10209 tut01-hello-world.cc \ 10210 -o tut01-hello-world \ 10211 -lgccjit 10212 @end example 10213 10214 You should then be able to run the built program: 10215 10216 @example 10217 $ ./tut01-hello-world 10218 hello world 10219 @end example 10220 10221 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 10222 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 10223 @c 10224 @c This is free software: you can redistribute it and/or modify it 10225 @c under the terms of the GNU General Public License as published by 10226 @c the Free Software Foundation, either version 3 of the License, or 10227 @c (at your option) any later version. 10228 @c 10229 @c This program is distributed in the hope that it will be useful, but 10230 @c WITHOUT ANY WARRANTY; without even the implied warranty of 10231 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10232 @c General Public License for more details. 10233 @c 10234 @c You should have received a copy of the GNU General Public License 10235 @c along with this program. If not, see 10236 @c <https://www.gnu.org/licenses/>. 10237 10238 @node Tutorial part 2 Creating a trivial machine code function<2>,Tutorial part 3 Loops and variables<2>,Tutorial part 1 Hello world<2>,Tutorial<2> 10239 @anchor{cp/intro/tutorial02 doc}@anchor{173}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{174} 10240 @subsection Tutorial part 2: Creating a trivial machine code function 10241 10242 10243 Consider this C function: 10244 10245 @example 10246 int square (int i) 10247 @{ 10248 return i * i; 10249 @} 10250 @end example 10251 10252 How can we construct this at run-time using libgccjits C++ API? 10253 10254 First we need to include the relevant header: 10255 10256 @example 10257 #include <libgccjit++.h> 10258 @end example 10259 10260 All state associated with compilation is associated with a 10261 @ref{175,,gccjit;;context}, which is a thin C++ wrapper around the C APIs 10262 @ref{8,,gcc_jit_context *}. 10263 10264 Create one using @ref{176,,gccjit;;context;;acquire()}: 10265 10266 @example 10267 gccjit::context ctxt; 10268 ctxt = gccjit::context::acquire (); 10269 @end example 10270 10271 The JIT library has a system of types. It is statically-typed: every 10272 expression is of a specific type, fixed at compile-time. In our example, 10273 all of the expressions are of the C @cite{int} type, so lets obtain this from 10274 the context, as a @ref{177,,gccjit;;type}, using 10275 @ref{178,,gccjit;;context;;get_type()}: 10276 10277 @example 10278 gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 10279 @end example 10280 10281 @ref{177,,gccjit;;type} is an example of a contextual object: every 10282 entity in the API is associated with a @ref{175,,gccjit;;context}. 10283 10284 Memory management is easy: all such contextual objects are automatically 10285 cleaned up for you when the context is released, using 10286 @ref{179,,gccjit;;context;;release()}: 10287 10288 @example 10289 ctxt.release (); 10290 @end example 10291 10292 so you dont need to manually track and cleanup all objects, just the 10293 contexts. 10294 10295 All of the C++ classes in the API are thin wrappers around pointers to 10296 types in the C API. 10297 10298 The C++ class hierarchy within the @code{gccjit} namespace looks like this: 10299 10300 @example 10301 +- object 10302 +- location 10303 +- type 10304 +- struct 10305 +- field 10306 +- function 10307 +- block 10308 +- rvalue 10309 +- lvalue 10310 +- param 10311 @end example 10312 10313 One thing you can do with a @ref{17a,,gccjit;;object} is 10314 to ask it for a human-readable description as a @code{std::string}, using 10315 @ref{17b,,gccjit;;object;;get_debug_string()}: 10316 10317 @example 10318 printf ("obj: %s\n", obj.get_debug_string ().c_str ()); 10319 @end example 10320 10321 giving this text on stdout: 10322 10323 @example 10324 obj: int 10325 @end example 10326 10327 This is invaluable when debugging. 10328 10329 Lets create the function. To do so, we first need to construct 10330 its single parameter, specifying its type and giving it a name, 10331 using @ref{17c,,gccjit;;context;;new_param()}: 10332 10333 @example 10334 gccjit::param param_i = ctxt.new_param (int_type, "i"); 10335 @end example 10336 10337 and we can then make a vector of all of the params of the function, 10338 in this case just one: 10339 10340 @example 10341 std::vector<gccjit::param> params; 10342 params.push_back (param_i); 10343 @end example 10344 10345 Now we can create the function, using 10346 @code{gccjit::context::new_function()}: 10347 10348 @example 10349 gccjit::function func = 10350 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10351 int_type, 10352 "square", 10353 params, 10354 0); 10355 @end example 10356 10357 To define the code within the function, we must create basic blocks 10358 containing statements. 10359 10360 Every basic block contains a list of statements, eventually terminated 10361 by a statement that either returns, or jumps to another basic block. 10362 10363 Our function has no control-flow, so we just need one basic block: 10364 10365 @example 10366 gccjit::block block = func.new_block (); 10367 @end example 10368 10369 Our basic block is relatively simple: it immediately terminates by 10370 returning the value of an expression. 10371 10372 We can build the expression using @ref{17d,,gccjit;;context;;new_binary_op()}: 10373 10374 @example 10375 gccjit::rvalue expr = 10376 ctxt.new_binary_op ( 10377 GCC_JIT_BINARY_OP_MULT, int_type, 10378 param_i, param_i); 10379 @end example 10380 10381 A @ref{17e,,gccjit;;rvalue} is another example of a 10382 @ref{17a,,gccjit;;object} subclass. As before, we can print it with 10383 @ref{17b,,gccjit;;object;;get_debug_string()}. 10384 10385 @example 10386 printf ("expr: %s\n", expr.get_debug_string ().c_str ()); 10387 @end example 10388 10389 giving this output: 10390 10391 @example 10392 expr: i * i 10393 @end example 10394 10395 Note that @ref{17e,,gccjit;;rvalue} provides numerous overloaded operators 10396 which can be used to dramatically reduce the amount of typing needed. 10397 We can build the above binary operation more directly with this one-liner: 10398 10399 @example 10400 gccjit::rvalue expr = param_i * param_i; 10401 @end example 10402 10403 Creating the expression in itself doesnt do anything; we have to add 10404 this expression to a statement within the block. In this case, we use it 10405 to build a return statement, which terminates the basic block: 10406 10407 @example 10408 block.end_with_return (expr); 10409 @end example 10410 10411 OK, weve populated the context. We can now compile it using 10412 @ref{17f,,gccjit;;context;;compile()}: 10413 10414 @example 10415 gcc_jit_result *result; 10416 result = ctxt.compile (); 10417 @end example 10418 10419 and get a @ref{16,,gcc_jit_result *}. 10420 10421 We can now use @ref{17,,gcc_jit_result_get_code()} to look up a specific 10422 machine code routine within the result, in this case, the function we 10423 created above. 10424 10425 @example 10426 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 10427 if (!fn_ptr) 10428 @{ 10429 fprintf (stderr, "NULL fn_ptr"); 10430 goto error; 10431 @} 10432 @end example 10433 10434 We can now cast the pointer to an appropriate function pointer type, and 10435 then call it: 10436 10437 @example 10438 typedef int (*fn_type) (int); 10439 fn_type square = (fn_type)fn_ptr; 10440 printf ("result: %d", square (5)); 10441 @end example 10442 10443 @example 10444 result: 25 10445 @end example 10446 10447 @menu 10448 * Options: Options<3>. 10449 * Full example: Full example<3>. 10450 10451 @end menu 10452 10453 @node Options<3>,Full example<3>,,Tutorial part 2 Creating a trivial machine code function<2> 10454 @anchor{cp/intro/tutorial02 options}@anchor{180} 10455 @subsubsection Options 10456 10457 10458 To get more information on whats going on, you can set debugging flags 10459 on the context using @ref{181,,gccjit;;context;;set_bool_option()}. 10460 10461 @c (I'm deliberately not mentioning 10462 @c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think 10463 @c it's probably more of use to implementors than to users) 10464 10465 Setting @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE} will dump a 10466 C-like representation to stderr when you compile (GCCs GIMPLE 10467 representation): 10468 10469 @example 10470 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); 10471 result = ctxt.compile (); 10472 @end example 10473 10474 @example 10475 square (signed int i) 10476 @{ 10477 signed int D.260; 10478 10479 entry: 10480 D.260 = i * i; 10481 return D.260; 10482 @} 10483 @end example 10484 10485 We can see the generated machine code in assembler form (on stderr) by 10486 setting @ref{1d,,GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE} on the context 10487 before compiling: 10488 10489 @example 10490 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1); 10491 result = ctxt.compile (); 10492 @end example 10493 10494 @example 10495 .file "fake.c" 10496 .text 10497 .globl square 10498 .type square, @@function 10499 square: 10500 .LFB6: 10501 .cfi_startproc 10502 pushq %rbp 10503 .cfi_def_cfa_offset 16 10504 .cfi_offset 6, -16 10505 movq %rsp, %rbp 10506 .cfi_def_cfa_register 6 10507 movl %edi, -4(%rbp) 10508 .L14: 10509 movl -4(%rbp), %eax 10510 imull -4(%rbp), %eax 10511 popq %rbp 10512 .cfi_def_cfa 7, 8 10513 ret 10514 .cfi_endproc 10515 .LFE6: 10516 .size square, .-square 10517 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 10518 .section .note.GNU-stack,"",@@progbits 10519 @end example 10520 10521 By default, no optimizations are performed, the equivalent of GCCs 10522 @cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling 10523 @ref{182,,gccjit;;context;;set_int_option()} with 10524 @ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 10525 10526 @example 10527 ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); 10528 @end example 10529 10530 @example 10531 .file "fake.c" 10532 .text 10533 .p2align 4,,15 10534 .globl square 10535 .type square, @@function 10536 square: 10537 .LFB7: 10538 .cfi_startproc 10539 .L16: 10540 movl %edi, %eax 10541 imull %edi, %eax 10542 ret 10543 .cfi_endproc 10544 .LFE7: 10545 .size square, .-square 10546 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 10547 .section .note.GNU-stack,"",@@progbits 10548 @end example 10549 10550 Naturally this has only a small effect on such a trivial function. 10551 10552 @node Full example<3>,,Options<3>,Tutorial part 2 Creating a trivial machine code function<2> 10553 @anchor{cp/intro/tutorial02 full-example}@anchor{183} 10554 @subsubsection Full example 10555 10556 10557 Heres what the above looks like as a complete program: 10558 10559 @quotation 10560 10561 @example 10562 /* Usage example for libgccjit.so's C++ API 10563 Copyright (C) 2014-2022 Free Software Foundation, Inc. 10564 10565 This file is part of GCC. 10566 10567 GCC is free software; you can redistribute it and/or modify it 10568 under the terms of the GNU General Public License as published by 10569 the Free Software Foundation; either version 3, or (at your option) 10570 any later version. 10571 10572 GCC is distributed in the hope that it will be useful, but 10573 WITHOUT ANY WARRANTY; without even the implied warranty of 10574 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10575 General Public License for more details. 10576 10577 You should have received a copy of the GNU General Public License 10578 along with GCC; see the file COPYING3. If not see 10579 <http://www.gnu.org/licenses/>. */ 10580 10581 #include <libgccjit++.h> 10582 10583 #include <stdlib.h> 10584 #include <stdio.h> 10585 10586 void 10587 create_code (gccjit::context ctxt) 10588 @{ 10589 /* Let's try to inject the equivalent of this C code: 10590 10591 int square (int i) 10592 @{ 10593 return i * i; 10594 @} 10595 */ 10596 gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 10597 gccjit::param param_i = ctxt.new_param (int_type, "i"); 10598 std::vector<gccjit::param> params; 10599 params.push_back (param_i); 10600 gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10601 int_type, 10602 "square", 10603 params, 0); 10604 10605 gccjit::block block = func.new_block (); 10606 10607 gccjit::rvalue expr = 10608 ctxt.new_binary_op (GCC_JIT_BINARY_OP_MULT, int_type, 10609 param_i, param_i); 10610 10611 block.end_with_return (expr); 10612 @} 10613 10614 int 10615 main (int argc, char **argv) 10616 @{ 10617 /* Get a "context" object for working with the library. */ 10618 gccjit::context ctxt = gccjit::context::acquire (); 10619 10620 /* Set some options on the context. 10621 Turn this on to see the code being generated, in assembler form. */ 10622 ctxt.set_bool_option ( 10623 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 10624 0); 10625 10626 /* Populate the context. */ 10627 create_code (ctxt); 10628 10629 /* Compile the code. */ 10630 gcc_jit_result *result = ctxt.compile (); 10631 10632 /* We're done with the context; we can release it: */ 10633 ctxt.release (); 10634 10635 if (!result) 10636 @{ 10637 fprintf (stderr, "NULL result"); 10638 return 1; 10639 @} 10640 10641 /* Extract the generated code from "result". */ 10642 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 10643 if (!fn_ptr) 10644 @{ 10645 fprintf (stderr, "NULL fn_ptr"); 10646 gcc_jit_result_release (result); 10647 return 1; 10648 @} 10649 10650 typedef int (*fn_type) (int); 10651 fn_type square = (fn_type)fn_ptr; 10652 printf ("result: %d\n", square (5)); 10653 10654 gcc_jit_result_release (result); 10655 return 0; 10656 @} 10657 @end example 10658 @end quotation 10659 10660 Building and running it: 10661 10662 @example 10663 $ gcc \ 10664 tut02-square.cc \ 10665 -o tut02-square \ 10666 -lgccjit 10667 10668 # Run the built program: 10669 $ ./tut02-square 10670 result: 25 10671 @end example 10672 10673 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 10674 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 10675 @c 10676 @c This is free software: you can redistribute it and/or modify it 10677 @c under the terms of the GNU General Public License as published by 10678 @c the Free Software Foundation, either version 3 of the License, or 10679 @c (at your option) any later version. 10680 @c 10681 @c This program is distributed in the hope that it will be useful, but 10682 @c WITHOUT ANY WARRANTY; without even the implied warranty of 10683 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10684 @c General Public License for more details. 10685 @c 10686 @c You should have received a copy of the GNU General Public License 10687 @c along with this program. If not, see 10688 @c <https://www.gnu.org/licenses/>. 10689 10690 @node Tutorial part 3 Loops and variables<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,Tutorial part 2 Creating a trivial machine code function<2>,Tutorial<2> 10691 @anchor{cp/intro/tutorial03 doc}@anchor{184}@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{185} 10692 @subsection Tutorial part 3: Loops and variables 10693 10694 10695 Consider this C function: 10696 10697 @quotation 10698 10699 @example 10700 int loop_test (int n) 10701 @{ 10702 int sum = 0; 10703 for (int i = 0; i < n; i++) 10704 sum += i * i; 10705 return sum; 10706 @} 10707 @end example 10708 @end quotation 10709 10710 This example demonstrates some more features of libgccjit, with local 10711 variables and a loop. 10712 10713 To break this down into libgccjit terms, its usually easier to reword 10714 the @cite{for} loop as a @cite{while} loop, giving: 10715 10716 @quotation 10717 10718 @example 10719 int loop_test (int n) 10720 @{ 10721 int sum = 0; 10722 int i = 0; 10723 while (i < n) 10724 @{ 10725 sum += i * i; 10726 i++; 10727 @} 10728 return sum; 10729 @} 10730 @end example 10731 @end quotation 10732 10733 Heres what the final control flow graph will look like: 10734 10735 @quotation 10736 10737 10738 @float Figure 10739 10740 @image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png} 10741 10742 @end float 10743 10744 @end quotation 10745 10746 As before, we include the libgccjit++ header and make a 10747 @ref{175,,gccjit;;context}. 10748 10749 @example 10750 #include <libgccjit++.h> 10751 10752 void test (void) 10753 @{ 10754 gccjit::context ctxt; 10755 ctxt = gccjit::context::acquire (); 10756 @end example 10757 10758 The function works with the C @cite{int} type. 10759 10760 In the previous tutorial we acquired this via 10761 10762 @example 10763 gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_INT); 10764 @end example 10765 10766 though we could equally well make it work on, say, @cite{double}: 10767 10768 @example 10769 gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_DOUBLE); 10770 @end example 10771 10772 For integer types we can use @code{gccjit::context::get_int_type} 10773 to directly bind a specific type: 10774 10775 @example 10776 gccjit::type the_type = ctxt.get_int_type <int> (); 10777 @end example 10778 10779 Lets build the function: 10780 10781 @example 10782 gcc_jit_param n = ctxt.new_param (the_type, "n"); 10783 std::vector<gccjit::param> params; 10784 params.push_back (n); 10785 gccjit::function func = 10786 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10787 return_type, 10788 "loop_test", 10789 params, 0); 10790 @end example 10791 10792 @menu 10793 * Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>. 10794 * Control flow: Control flow<2>. 10795 * Visualizing the control flow graph: Visualizing the control flow graph<2>. 10796 * Full example: Full example<4>. 10797 10798 @end menu 10799 10800 @node Expressions lvalues and rvalues<2>,Control flow<2>,,Tutorial part 3 Loops and variables<2> 10801 @anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{186} 10802 @subsubsection Expressions: lvalues and rvalues 10803 10804 10805 The base class of expression is the @ref{17e,,gccjit;;rvalue}, 10806 representing an expression that can be on the @emph{right}-hand side of 10807 an assignment: a value that can be computed somehow, and assigned 10808 @emph{to} a storage area (such as a variable). It has a specific 10809 @ref{177,,gccjit;;type}. 10810 10811 Anothe important class is @ref{187,,gccjit;;lvalue}. 10812 A @ref{187,,gccjit;;lvalue}. is something that can of the @emph{left}-hand 10813 side of an assignment: a storage area (such as a variable). 10814 10815 In other words, every assignment can be thought of as: 10816 10817 @example 10818 LVALUE = RVALUE; 10819 @end example 10820 10821 Note that @ref{187,,gccjit;;lvalue} is a subclass of 10822 @ref{17e,,gccjit;;rvalue}, where in an assignment of the form: 10823 10824 @example 10825 LVALUE_A = LVALUE_B; 10826 @end example 10827 10828 the @cite{LVALUE_B} implies reading the current value of that storage 10829 area, assigning it into the @cite{LVALUE_A}. 10830 10831 So far the only expressions weve seen are from the previous tutorial: 10832 10833 10834 @enumerate 10835 10836 @item 10837 the multiplication @cite{i * i}: 10838 @end enumerate 10839 10840 @quotation 10841 10842 @example 10843 gccjit::rvalue expr = 10844 ctxt.new_binary_op ( 10845 GCC_JIT_BINARY_OP_MULT, int_type, 10846 param_i, param_i); 10847 10848 /* Alternatively, using operator-overloading: */ 10849 gccjit::rvalue expr = param_i * param_i; 10850 @end example 10851 10852 which is a @ref{17e,,gccjit;;rvalue}, and 10853 @end quotation 10854 10855 10856 @enumerate 2 10857 10858 @item 10859 the various function parameters: @cite{param_i} and @cite{param_n}, instances of 10860 @ref{188,,gccjit;;param}, which is a subclass of @ref{187,,gccjit;;lvalue} 10861 (and, in turn, of @ref{17e,,gccjit;;rvalue}): 10862 we can both read from and write to function parameters within the 10863 body of a function. 10864 @end enumerate 10865 10866 Our new example has a new kind of expression: we have two local 10867 variables. We create them by calling 10868 @ref{189,,gccjit;;function;;new_local()}, supplying a type and a name: 10869 10870 @example 10871 /* Build locals: */ 10872 gccjit::lvalue i = func.new_local (the_type, "i"); 10873 gccjit::lvalue sum = func.new_local (the_type, "sum"); 10874 @end example 10875 10876 These are instances of @ref{187,,gccjit;;lvalue} - they can be read from 10877 and written to. 10878 10879 Note that there is no precanned way to create @emph{and} initialize a variable 10880 like in C: 10881 10882 @example 10883 int i = 0; 10884 @end example 10885 10886 Instead, having added the local to the function, we have to separately add 10887 an assignment of @cite{0} to @cite{local_i} at the beginning of the function. 10888 10889 @node Control flow<2>,Visualizing the control flow graph<2>,Expressions lvalues and rvalues<2>,Tutorial part 3 Loops and variables<2> 10890 @anchor{cp/intro/tutorial03 control-flow}@anchor{18a} 10891 @subsubsection Control flow 10892 10893 10894 This function has a loop, so we need to build some basic blocks to 10895 handle the control flow. In this case, we need 4 blocks: 10896 10897 10898 @enumerate 10899 10900 @item 10901 before the loop (initializing the locals) 10902 10903 @item 10904 the conditional at the top of the loop (comparing @cite{i < n}) 10905 10906 @item 10907 the body of the loop 10908 10909 @item 10910 after the loop terminates (@cite{return sum}) 10911 @end enumerate 10912 10913 so we create these as @ref{18b,,gccjit;;block} instances within the 10914 @ref{18c,,gccjit;;function}: 10915 10916 @example 10917 gccjit::block b_initial = func.new_block ("initial"); 10918 gccjit::block b_loop_cond = func.new_block ("loop_cond"); 10919 gccjit::block b_loop_body = func.new_block ("loop_body"); 10920 gccjit::block b_after_loop = func.new_block ("after_loop"); 10921 @end example 10922 10923 We now populate each block with statements. 10924 10925 The entry block @cite{b_initial} consists of initializations followed by a jump 10926 to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using 10927 @ref{18d,,gccjit;;block;;add_assignment()} to add 10928 an assignment statement, and using @ref{18e,,gccjit;;context;;zero()} to get 10929 the constant value @cite{0} for the relevant type for the right-hand side of 10930 the assignment: 10931 10932 @example 10933 /* sum = 0; */ 10934 b_initial.add_assignment (sum, ctxt.zero (the_type)); 10935 10936 /* i = 0; */ 10937 b_initial.add_assignment (i, ctxt.zero (the_type)); 10938 @end example 10939 10940 We can then terminate the entry block by jumping to the conditional: 10941 10942 @example 10943 b_initial.end_with_jump (b_loop_cond); 10944 @end example 10945 10946 The conditional block is equivalent to the line @cite{while (i < n)} from our 10947 C example. It contains a single statement: a conditional, which jumps to 10948 one of two destination blocks depending on a boolean 10949 @ref{17e,,gccjit;;rvalue}, in this case the comparison of @cite{i} and @cite{n}. 10950 10951 We could build the comparison using @ref{18f,,gccjit;;context;;new_comparison()}: 10952 10953 @example 10954 gccjit::rvalue guard = 10955 ctxt.new_comparison (GCC_JIT_COMPARISON_GE, 10956 i, n); 10957 @end example 10958 10959 and can then use this to add @cite{b_loop_cond}s sole statement, via 10960 @ref{190,,gccjit;;block;;end_with_conditional()}: 10961 10962 @example 10963 b_loop_cond.end_with_conditional (guard, 10964 b_after_loop, // on_true 10965 b_loop_body); // on_false 10966 @end example 10967 10968 However @ref{17e,,gccjit;;rvalue} has overloaded operators for this, so we 10969 express the conditional as 10970 10971 @example 10972 gccjit::rvalue guard = (i >= n); 10973 @end example 10974 10975 and hence we can write the block more concisely as: 10976 10977 @example 10978 b_loop_cond.end_with_conditional ( 10979 i >= n, 10980 b_after_loop, // on_true 10981 b_loop_body); // on_false 10982 @end example 10983 10984 Next, we populate the body of the loop. 10985 10986 The C statement @cite{sum += i * i;} is an assignment operation, where an 10987 lvalue is modified in-place. We use 10988 @ref{191,,gccjit;;block;;add_assignment_op()} to handle these operations: 10989 10990 @example 10991 /* sum += i * i */ 10992 b_loop_body.add_assignment_op (sum, 10993 GCC_JIT_BINARY_OP_PLUS, 10994 i * i); 10995 @end example 10996 10997 The @cite{i++} can be thought of as @cite{i += 1}, and can thus be handled in 10998 a similar way. We use @ref{2f,,gcc_jit_context_one()} to get the constant 10999 value @cite{1} (for the relevant type) for the right-hand side 11000 of the assignment. 11001 11002 @example 11003 /* i++ */ 11004 b_loop_body.add_assignment_op (i, 11005 GCC_JIT_BINARY_OP_PLUS, 11006 ctxt.one (the_type)); 11007 @end example 11008 11009 @cartouche 11010 @quotation Note 11011 For numeric constants other than 0 or 1, we could use 11012 @ref{192,,gccjit;;context;;new_rvalue()}, which has overloads 11013 for both @code{int} and @code{double}. 11014 @end quotation 11015 @end cartouche 11016 11017 The loop body completes by jumping back to the conditional: 11018 11019 @example 11020 b_loop_body.end_with_jump (b_loop_cond); 11021 @end example 11022 11023 Finally, we populate the @cite{b_after_loop} block, reached when the loop 11024 conditional is false. We want to generate the equivalent of: 11025 11026 @example 11027 return sum; 11028 @end example 11029 11030 so the block is just one statement: 11031 11032 @example 11033 /* return sum */ 11034 b_after_loop.end_with_return (sum); 11035 @end example 11036 11037 @cartouche 11038 @quotation Note 11039 You can intermingle block creation with statement creation, 11040 but given that the terminator statements generally include references 11041 to other blocks, I find its clearer to create all the blocks, 11042 @emph{then} all the statements. 11043 @end quotation 11044 @end cartouche 11045 11046 Weve finished populating the function. As before, we can now compile it 11047 to machine code: 11048 11049 @example 11050 gcc_jit_result *result; 11051 result = ctxt.compile (); 11052 11053 ctxt.release (); 11054 11055 if (!result) 11056 @{ 11057 fprintf (stderr, "NULL result"); 11058 return 1; 11059 @} 11060 11061 typedef int (*loop_test_fn_type) (int); 11062 loop_test_fn_type loop_test = 11063 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 11064 if (!loop_test) 11065 @{ 11066 fprintf (stderr, "NULL loop_test"); 11067 gcc_jit_result_release (result); 11068 return 1; 11069 @} 11070 printf ("result: %d", loop_test (10)); 11071 @end example 11072 11073 @example 11074 result: 285 11075 @end example 11076 11077 @node Visualizing the control flow graph<2>,Full example<4>,Control flow<2>,Tutorial part 3 Loops and variables<2> 11078 @anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{193} 11079 @subsubsection Visualizing the control flow graph 11080 11081 11082 You can see the control flow graph of a function using 11083 @ref{194,,gccjit;;function;;dump_to_dot()}: 11084 11085 @example 11086 func.dump_to_dot ("/tmp/sum-of-squares.dot"); 11087 @end example 11088 11089 giving a .dot file in GraphViz format. 11090 11091 You can convert this to an image using @cite{dot}: 11092 11093 @example 11094 $ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png 11095 @end example 11096 11097 or use a viewer (my preferred one is xdot.py; see 11098 @indicateurl{https://github.com/jrfonseca/xdot.py}; on Fedora you can 11099 install it with @cite{yum install python-xdot}): 11100 11101 @quotation 11102 11103 11104 @float Figure 11105 11106 @image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png} 11107 11108 @end float 11109 11110 @end quotation 11111 11112 @node Full example<4>,,Visualizing the control flow graph<2>,Tutorial part 3 Loops and variables<2> 11113 @anchor{cp/intro/tutorial03 full-example}@anchor{195} 11114 @subsubsection Full example 11115 11116 11117 @quotation 11118 11119 @example 11120 /* Usage example for libgccjit.so's C++ API 11121 Copyright (C) 2014-2022 Free Software Foundation, Inc. 11122 11123 This file is part of GCC. 11124 11125 GCC is free software; you can redistribute it and/or modify it 11126 under the terms of the GNU General Public License as published by 11127 the Free Software Foundation; either version 3, or (at your option) 11128 any later version. 11129 11130 GCC is distributed in the hope that it will be useful, but 11131 WITHOUT ANY WARRANTY; without even the implied warranty of 11132 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11133 General Public License for more details. 11134 11135 You should have received a copy of the GNU General Public License 11136 along with GCC; see the file COPYING3. If not see 11137 <http://www.gnu.org/licenses/>. */ 11138 11139 #include <libgccjit++.h> 11140 11141 #include <stdlib.h> 11142 #include <stdio.h> 11143 11144 void 11145 create_code (gccjit::context ctxt) 11146 @{ 11147 /* 11148 Simple sum-of-squares, to test conditionals and looping 11149 11150 int loop_test (int n) 11151 @{ 11152 int i; 11153 int sum = 0; 11154 for (i = 0; i < n ; i ++) 11155 @{ 11156 sum += i * i; 11157 @} 11158 return sum; 11159 */ 11160 gccjit::type the_type = ctxt.get_int_type <int> (); 11161 gccjit::type return_type = the_type; 11162 11163 gccjit::param n = ctxt.new_param (the_type, "n"); 11164 std::vector<gccjit::param> params; 11165 params.push_back (n); 11166 gccjit::function func = 11167 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 11168 return_type, 11169 "loop_test", 11170 params, 0); 11171 11172 /* Build locals: */ 11173 gccjit::lvalue i = func.new_local (the_type, "i"); 11174 gccjit::lvalue sum = func.new_local (the_type, "sum"); 11175 11176 gccjit::block b_initial = func.new_block ("initial"); 11177 gccjit::block b_loop_cond = func.new_block ("loop_cond"); 11178 gccjit::block b_loop_body = func.new_block ("loop_body"); 11179 gccjit::block b_after_loop = func.new_block ("after_loop"); 11180 11181 /* sum = 0; */ 11182 b_initial.add_assignment (sum, ctxt.zero (the_type)); 11183 11184 /* i = 0; */ 11185 b_initial.add_assignment (i, ctxt.zero (the_type)); 11186 11187 b_initial.end_with_jump (b_loop_cond); 11188 11189 /* if (i >= n) */ 11190 b_loop_cond.end_with_conditional ( 11191 i >= n, 11192 b_after_loop, 11193 b_loop_body); 11194 11195 /* sum += i * i */ 11196 b_loop_body.add_assignment_op (sum, 11197 GCC_JIT_BINARY_OP_PLUS, 11198 i * i); 11199 11200 /* i++ */ 11201 b_loop_body.add_assignment_op (i, 11202 GCC_JIT_BINARY_OP_PLUS, 11203 ctxt.one (the_type)); 11204 11205 b_loop_body.end_with_jump (b_loop_cond); 11206 11207 /* return sum */ 11208 b_after_loop.end_with_return (sum); 11209 @} 11210 11211 int 11212 main (int argc, char **argv) 11213 @{ 11214 gccjit::context ctxt; 11215 gcc_jit_result *result = NULL; 11216 11217 /* Get a "context" object for working with the library. */ 11218 ctxt = gccjit::context::acquire (); 11219 11220 /* Set some options on the context. 11221 Turn this on to see the code being generated, in assembler form. */ 11222 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 11223 0); 11224 11225 /* Populate the context. */ 11226 create_code (ctxt); 11227 11228 /* Compile the code. */ 11229 result = ctxt.compile (); 11230 11231 ctxt.release (); 11232 11233 if (!result) 11234 @{ 11235 fprintf (stderr, "NULL result"); 11236 return 1; 11237 @} 11238 11239 /* Extract the generated code from "result". */ 11240 typedef int (*loop_test_fn_type) (int); 11241 loop_test_fn_type loop_test = 11242 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 11243 if (!loop_test) 11244 @{ 11245 fprintf (stderr, "NULL loop_test"); 11246 gcc_jit_result_release (result); 11247 return 1; 11248 @} 11249 11250 /* Run the generated code. */ 11251 int val = loop_test (10); 11252 printf("loop_test returned: %d\n", val); 11253 11254 gcc_jit_result_release (result); 11255 return 0; 11256 @} 11257 @end example 11258 @end quotation 11259 11260 Building and running it: 11261 11262 @example 11263 $ gcc \ 11264 tut03-sum-of-squares.cc \ 11265 -o tut03-sum-of-squares \ 11266 -lgccjit 11267 11268 # Run the built program: 11269 $ ./tut03-sum-of-squares 11270 loop_test returned: 285 11271 @end example 11272 11273 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 11274 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 11275 @c 11276 @c This is free software: you can redistribute it and/or modify it 11277 @c under the terms of the GNU General Public License as published by 11278 @c the Free Software Foundation, either version 3 of the License, or 11279 @c (at your option) any later version. 11280 @c 11281 @c This program is distributed in the hope that it will be useful, but 11282 @c WITHOUT ANY WARRANTY; without even the implied warranty of 11283 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11284 @c General Public License for more details. 11285 @c 11286 @c You should have received a copy of the GNU General Public License 11287 @c along with this program. If not, see 11288 @c <https://www.gnu.org/licenses/>. 11289 11290 @node Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,,Tutorial part 3 Loops and variables<2>,Tutorial<2> 11291 @anchor{cp/intro/tutorial04 doc}@anchor{196}@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{197} 11292 @subsection Tutorial part 4: Adding JIT-compilation to a toy interpreter 11293 11294 11295 In this example we construct a toy interpreter, and add JIT-compilation 11296 to it. 11297 11298 @menu 11299 * Our toy interpreter: Our toy interpreter<2>. 11300 * Compiling to machine code: Compiling to machine code<2>. 11301 * Setting things up: Setting things up<2>. 11302 * Populating the function: Populating the function<2>. 11303 * Verifying the control flow graph: Verifying the control flow graph<2>. 11304 * Compiling the context: Compiling the context<2>. 11305 * Single-stepping through the generated code: Single-stepping through the generated code<2>. 11306 * Examining the generated code: Examining the generated code<2>. 11307 * Putting it all together: Putting it all together<2>. 11308 * Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>. 11309 11310 @end menu 11311 11312 @node Our toy interpreter<2>,Compiling to machine code<2>,,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 11313 @anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{198} 11314 @subsubsection Our toy interpreter 11315 11316 11317 Its a stack-based interpreter, and is intended as a (very simple) example 11318 of the kind of bytecode interpreter seen in dynamic languages such as 11319 Python, Ruby etc. 11320 11321 For the sake of simplicity, our toy virtual machine is very limited: 11322 11323 @quotation 11324 11325 11326 @itemize * 11327 11328 @item 11329 The only data type is @cite{int} 11330 11331 @item 11332 It can only work on one function at a time (so that the only 11333 function call that can be made is to recurse). 11334 11335 @item 11336 Functions can only take one parameter. 11337 11338 @item 11339 Functions have a stack of @cite{int} values. 11340 11341 @item 11342 Well implement function call within the interpreter by calling a 11343 function in our implementation, rather than implementing our own 11344 frame stack. 11345 11346 @item 11347 The parser is only good enough to get the examples to work. 11348 @end itemize 11349 @end quotation 11350 11351 Naturally, a real interpreter would be much more complicated that this. 11352 11353 The following operations are supported: 11354 11355 11356 @multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxx} 11357 @headitem 11358 11359 Operation 11360 11361 @tab 11362 11363 Meaning 11364 11365 @tab 11366 11367 Old Stack 11368 11369 @tab 11370 11371 New Stack 11372 11373 @item 11374 11375 DUP 11376 11377 @tab 11378 11379 Duplicate top of stack. 11380 11381 @tab 11382 11383 @code{[..., x]} 11384 11385 @tab 11386 11387 @code{[..., x, x]} 11388 11389 @item 11390 11391 ROT 11392 11393 @tab 11394 11395 Swap top two elements 11396 of stack. 11397 11398 @tab 11399 11400 @code{[..., x, y]} 11401 11402 @tab 11403 11404 @code{[..., y, x]} 11405 11406 @item 11407 11408 BINARY_ADD 11409 11410 @tab 11411 11412 Add the top two elements 11413 on the stack. 11414 11415 @tab 11416 11417 @code{[..., x, y]} 11418 11419 @tab 11420 11421 @code{[..., (x+y)]} 11422 11423 @item 11424 11425 BINARY_SUBTRACT 11426 11427 @tab 11428 11429 Likewise, but subtract. 11430 11431 @tab 11432 11433 @code{[..., x, y]} 11434 11435 @tab 11436 11437 @code{[..., (x-y)]} 11438 11439 @item 11440 11441 BINARY_MULT 11442 11443 @tab 11444 11445 Likewise, but multiply. 11446 11447 @tab 11448 11449 @code{[..., x, y]} 11450 11451 @tab 11452 11453 @code{[..., (x*y)]} 11454 11455 @item 11456 11457 BINARY_COMPARE_LT 11458 11459 @tab 11460 11461 Compare the top two 11462 elements on the stack 11463 and push a nonzero/zero 11464 if (x<y). 11465 11466 @tab 11467 11468 @code{[..., x, y]} 11469 11470 @tab 11471 11472 @code{[..., (x<y)]} 11473 11474 @item 11475 11476 RECURSE 11477 11478 @tab 11479 11480 Recurse, passing the top 11481 of the stack, and 11482 popping the result. 11483 11484 @tab 11485 11486 @code{[..., x]} 11487 11488 @tab 11489 11490 @code{[..., fn(x)]} 11491 11492 @item 11493 11494 RETURN 11495 11496 @tab 11497 11498 Return the top of the 11499 stack. 11500 11501 @tab 11502 11503 @code{[x]} 11504 11505 @tab 11506 11507 @code{[]} 11508 11509 @item 11510 11511 PUSH_CONST @cite{arg} 11512 11513 @tab 11514 11515 Push an int const. 11516 11517 @tab 11518 11519 @code{[...]} 11520 11521 @tab 11522 11523 @code{[..., arg]} 11524 11525 @item 11526 11527 JUMP_ABS_IF_TRUE @cite{arg} 11528 11529 @tab 11530 11531 Pop; if top of stack was 11532 nonzero, jump to 11533 @code{arg}. 11534 11535 @tab 11536 11537 @code{[..., x]} 11538 11539 @tab 11540 11541 @code{[...]} 11542 11543 @end multitable 11544 11545 11546 Programs can be interpreted, disassembled, and compiled to machine code. 11547 11548 The interpreter reads @code{.toy} scripts. Heres what a simple recursive 11549 factorial program looks like, the script @code{factorial.toy}. 11550 The parser ignores lines beginning with a @cite{#}. 11551 11552 @quotation 11553 11554 @example 11555 # Simple recursive factorial implementation, roughly equivalent to: 11556 # 11557 # int factorial (int arg) 11558 # @{ 11559 # if (arg < 2) 11560 # return arg 11561 # return arg * factorial (arg - 1) 11562 # @} 11563 11564 # Initial state: 11565 # stack: [arg] 11566 11567 # 0: 11568 DUP 11569 # stack: [arg, arg] 11570 11571 # 1: 11572 PUSH_CONST 2 11573 # stack: [arg, arg, 2] 11574 11575 # 2: 11576 BINARY_COMPARE_LT 11577 # stack: [arg, (arg < 2)] 11578 11579 # 3: 11580 JUMP_ABS_IF_TRUE 9 11581 # stack: [arg] 11582 11583 # 4: 11584 DUP 11585 # stack: [arg, arg] 11586 11587 # 5: 11588 PUSH_CONST 1 11589 # stack: [arg, arg, 1] 11590 11591 # 6: 11592 BINARY_SUBTRACT 11593 # stack: [arg, (arg - 1) 11594 11595 # 7: 11596 RECURSE 11597 # stack: [arg, factorial(arg - 1)] 11598 11599 # 8: 11600 BINARY_MULT 11601 # stack: [arg * factorial(arg - 1)] 11602 11603 # 9: 11604 RETURN 11605 @end example 11606 @end quotation 11607 11608 The interpreter is a simple infinite loop with a big @code{switch} statement 11609 based on what the next opcode is: 11610 11611 @quotation 11612 11613 @example 11614 11615 int 11616 toyvm_function::interpret (int arg, FILE *trace) 11617 @{ 11618 toyvm_frame frame; 11619 #define PUSH(ARG) (frame.push (ARG)) 11620 #define POP(ARG) (frame.pop ()) 11621 11622 frame.frm_function = this; 11623 frame.frm_pc = 0; 11624 frame.frm_cur_depth = 0; 11625 11626 PUSH (arg); 11627 11628 while (1) 11629 @{ 11630 toyvm_op *op; 11631 int x, y; 11632 assert (frame.frm_pc < fn_num_ops); 11633 op = &fn_ops[frame.frm_pc++]; 11634 11635 if (trace) 11636 @{ 11637 frame.dump_stack (trace); 11638 disassemble_op (op, frame.frm_pc, trace); 11639 @} 11640 11641 switch (op->op_opcode) 11642 @{ 11643 /* Ops taking no operand. */ 11644 case DUP: 11645 x = POP (); 11646 PUSH (x); 11647 PUSH (x); 11648 break; 11649 11650 case ROT: 11651 y = POP (); 11652 x = POP (); 11653 PUSH (y); 11654 PUSH (x); 11655 break; 11656 11657 case BINARY_ADD: 11658 y = POP (); 11659 x = POP (); 11660 PUSH (x + y); 11661 break; 11662 11663 case BINARY_SUBTRACT: 11664 y = POP (); 11665 x = POP (); 11666 PUSH (x - y); 11667 break; 11668 11669 case BINARY_MULT: 11670 y = POP (); 11671 x = POP (); 11672 PUSH (x * y); 11673 break; 11674 11675 case BINARY_COMPARE_LT: 11676 y = POP (); 11677 x = POP (); 11678 PUSH (x < y); 11679 break; 11680 11681 case RECURSE: 11682 x = POP (); 11683 x = interpret (x, trace); 11684 PUSH (x); 11685 break; 11686 11687 case RETURN: 11688 return POP (); 11689 11690 /* Ops taking an operand. */ 11691 case PUSH_CONST: 11692 PUSH (op->op_operand); 11693 break; 11694 11695 case JUMP_ABS_IF_TRUE: 11696 x = POP (); 11697 if (x) 11698 frame.frm_pc = op->op_operand; 11699 break; 11700 11701 default: 11702 assert (0); /* unknown opcode */ 11703 11704 @} /* end of switch on opcode */ 11705 @} /* end of while loop */ 11706 11707 #undef PUSH 11708 #undef POP 11709 @} 11710 11711 @end example 11712 @end quotation 11713 11714 @node Compiling to machine code<2>,Setting things up<2>,Our toy interpreter<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 11715 @anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{199} 11716 @subsubsection Compiling to machine code 11717 11718 11719 We want to generate machine code that can be cast to this type and 11720 then directly executed in-process: 11721 11722 @quotation 11723 11724 @example 11725 typedef int (*toyvm_compiled_func) (int); 11726 11727 @end example 11728 @end quotation 11729 11730 Our compiler isnt very sophisticated; it takes the implementation of 11731 each opcode above, and maps it directly to the operations supported by 11732 the libgccjit API. 11733 11734 How should we handle the stack? In theory we could calculate what the 11735 stack depth will be at each opcode, and optimize away the stack 11736 manipulation by hand. Well see below that libgccjit is able to do 11737 this for us, so well implement stack manipulation 11738 in a direct way, by creating a @code{stack} array and @code{stack_depth} 11739 variables, local within the generated function, equivalent to this C code: 11740 11741 @example 11742 int stack_depth; 11743 int stack[MAX_STACK_DEPTH]; 11744 @end example 11745 11746 Well also have local variables @code{x} and @code{y} for use when implementing 11747 the opcodes, equivalent to this: 11748 11749 @example 11750 int x; 11751 int y; 11752 @end example 11753 11754 This means our compiler has the following state: 11755 11756 @quotation 11757 11758 @example 11759 11760 toyvm_function &toyvmfn; 11761 11762 gccjit::context ctxt; 11763 11764 gccjit::type int_type; 11765 gccjit::type bool_type; 11766 gccjit::type stack_type; /* int[MAX_STACK_DEPTH] */ 11767 11768 gccjit::rvalue const_one; 11769 11770 gccjit::function fn; 11771 gccjit::param param_arg; 11772 gccjit::lvalue stack; 11773 gccjit::lvalue stack_depth; 11774 gccjit::lvalue x; 11775 gccjit::lvalue y; 11776 11777 gccjit::location op_locs[MAX_OPS]; 11778 gccjit::block initial_block; 11779 gccjit::block op_blocks[MAX_OPS]; 11780 11781 @end example 11782 @end quotation 11783 11784 @node Setting things up<2>,Populating the function<2>,Compiling to machine code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 11785 @anchor{cp/intro/tutorial04 setting-things-up}@anchor{19a} 11786 @subsubsection Setting things up 11787 11788 11789 First we create our types: 11790 11791 @quotation 11792 11793 @example 11794 11795 void 11796 compilation_state::create_types () 11797 @{ 11798 /* Create types. */ 11799 int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 11800 bool_type = ctxt.get_type (GCC_JIT_TYPE_BOOL); 11801 stack_type = ctxt.new_array_type (int_type, MAX_STACK_DEPTH); 11802 11803 @end example 11804 @end quotation 11805 11806 along with extracting a useful @cite{int} constant: 11807 11808 @quotation 11809 11810 @example 11811 const_one = ctxt.one (int_type); 11812 11813 @} 11814 11815 @end example 11816 @end quotation 11817 11818 Well implement push and pop in terms of the @code{stack} array and 11819 @code{stack_depth}. Here are helper functions for adding statements to 11820 a block, implementing pushing and popping values: 11821 11822 @quotation 11823 11824 @example 11825 11826 void 11827 compilation_state::add_push (gccjit::block block, 11828 gccjit::rvalue rvalue, 11829 gccjit::location loc) 11830 @{ 11831 /* stack[stack_depth] = RVALUE */ 11832 block.add_assignment ( 11833 /* stack[stack_depth] */ 11834 ctxt.new_array_access ( 11835 stack, 11836 stack_depth, 11837 loc), 11838 rvalue, 11839 loc); 11840 11841 /* "stack_depth++;". */ 11842 block.add_assignment_op ( 11843 stack_depth, 11844 GCC_JIT_BINARY_OP_PLUS, 11845 const_one, 11846 loc); 11847 @} 11848 11849 void 11850 compilation_state::add_pop (gccjit::block block, 11851 gccjit::lvalue lvalue, 11852 gccjit::location loc) 11853 @{ 11854 /* "--stack_depth;". */ 11855 block.add_assignment_op ( 11856 stack_depth, 11857 GCC_JIT_BINARY_OP_MINUS, 11858 const_one, 11859 loc); 11860 11861 /* "LVALUE = stack[stack_depth];". */ 11862 block.add_assignment ( 11863 lvalue, 11864 /* stack[stack_depth] */ 11865 ctxt.new_array_access (stack, 11866 stack_depth, 11867 loc), 11868 loc); 11869 @} 11870 11871 @end example 11872 @end quotation 11873 11874 We will support single-stepping through the generated code in the 11875 debugger, so we need to create @ref{19b,,gccjit;;location} instances, one 11876 per operation in the source code. These will reference the lines of 11877 e.g. @code{factorial.toy}. 11878 11879 @quotation 11880 11881 @example 11882 11883 void 11884 compilation_state::create_locations () 11885 @{ 11886 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 11887 @{ 11888 toyvm_op *op = &toyvmfn.fn_ops[pc]; 11889 11890 op_locs[pc] = ctxt.new_location (toyvmfn.fn_filename, 11891 op->op_linenum, 11892 0); /* column */ 11893 @} 11894 @} 11895 11896 @end example 11897 @end quotation 11898 11899 Lets create the function itself. As usual, we create its parameter 11900 first, then use the parameter to create the function: 11901 11902 @quotation 11903 11904 @example 11905 11906 void 11907 compilation_state::create_function (const char *funcname) 11908 @{ 11909 std::vector <gccjit::param> params; 11910 param_arg = ctxt.new_param (int_type, "arg", op_locs[0]); 11911 params.push_back (param_arg); 11912 fn = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 11913 int_type, 11914 funcname, 11915 params, 0, 11916 op_locs[0]); 11917 11918 @end example 11919 @end quotation 11920 11921 We create the locals within the function. 11922 11923 @quotation 11924 11925 @example 11926 stack = fn.new_local (stack_type, "stack"); 11927 stack_depth = fn.new_local (int_type, "stack_depth"); 11928 x = fn.new_local (int_type, "x"); 11929 y = fn.new_local (int_type, "y"); 11930 11931 @end example 11932 @end quotation 11933 11934 @node Populating the function<2>,Verifying the control flow graph<2>,Setting things up<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 11935 @anchor{cp/intro/tutorial04 populating-the-function}@anchor{19c} 11936 @subsubsection Populating the function 11937 11938 11939 Theres some one-time initialization, and the API treats the first block 11940 you create as the entrypoint of the function, so we need to create that 11941 block first: 11942 11943 @quotation 11944 11945 @example 11946 initial_block = fn.new_block ("initial"); 11947 11948 @end example 11949 @end quotation 11950 11951 We can now create blocks for each of the operations. Most of these will 11952 be consolidated into larger blocks when the optimizer runs. 11953 11954 @quotation 11955 11956 @example 11957 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 11958 @{ 11959 char buf[100]; 11960 sprintf (buf, "instr%i", pc); 11961 op_blocks[pc] = fn.new_block (buf); 11962 @} 11963 11964 @end example 11965 @end quotation 11966 11967 Now that we have a block it can jump to when its done, we can populate 11968 the initial block: 11969 11970 @quotation 11971 11972 @example 11973 11974 /* "stack_depth = 0;". */ 11975 initial_block.add_assignment (stack_depth, 11976 ctxt.zero (int_type), 11977 op_locs[0]); 11978 11979 /* "PUSH (arg);". */ 11980 add_push (initial_block, 11981 param_arg, 11982 op_locs[0]); 11983 11984 /* ...and jump to insn 0. */ 11985 initial_block.end_with_jump (op_blocks[0], 11986 op_locs[0]); 11987 11988 @end example 11989 @end quotation 11990 11991 We can now populate the blocks for the individual operations. We loop 11992 through them, adding instructions to their blocks: 11993 11994 @quotation 11995 11996 @example 11997 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 11998 @{ 11999 gccjit::location loc = op_locs[pc]; 12000 12001 gccjit::block block = op_blocks[pc]; 12002 gccjit::block next_block = (pc < toyvmfn.fn_num_ops 12003 ? op_blocks[pc + 1] 12004 : NULL); 12005 12006 toyvm_op *op; 12007 op = &toyvmfn.fn_ops[pc]; 12008 12009 @end example 12010 @end quotation 12011 12012 Were going to have another big @code{switch} statement for implementing 12013 the opcodes, this time for compiling them, rather than interpreting 12014 them. Its helpful to have macros for implementing push and pop, so that 12015 we can make the @code{switch} statement thats coming up look as much as 12016 possible like the one above within the interpreter: 12017 12018 @example 12019 12020 #define X_EQUALS_POP()\ 12021 add_pop (block, x, loc) 12022 #define Y_EQUALS_POP()\ 12023 add_pop (block, y, loc) 12024 #define PUSH_RVALUE(RVALUE)\ 12025 add_push (block, (RVALUE), loc) 12026 #define PUSH_X()\ 12027 PUSH_RVALUE (x) 12028 #define PUSH_Y() \ 12029 PUSH_RVALUE (y) 12030 12031 @end example 12032 12033 @cartouche 12034 @quotation Note 12035 A particularly clever implementation would have an @emph{identical} 12036 @code{switch} statement shared by the interpreter and the compiler, with 12037 some preprocessor magic. Were not doing that here, for the sake 12038 of simplicity. 12039 @end quotation 12040 @end cartouche 12041 12042 When I first implemented this compiler, I accidentally missed an edit 12043 when copying and pasting the @code{Y_EQUALS_POP} macro, so that popping the 12044 stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y} 12045 uninitialized. 12046 12047 To track this kind of thing down, we can use 12048 @ref{19d,,gccjit;;block;;add_comment()} to add descriptive comments 12049 to the internal representation. This is invaluable when looking through 12050 the generated IR for, say @code{factorial}: 12051 12052 @quotation 12053 12054 @example 12055 12056 block.add_comment (opcode_names[op->op_opcode], loc); 12057 12058 @end example 12059 @end quotation 12060 12061 We can now write the big @code{switch} statement that implements the 12062 individual opcodes, populating the relevant block with statements: 12063 12064 @quotation 12065 12066 @example 12067 12068 switch (op->op_opcode) 12069 @{ 12070 case DUP: 12071 X_EQUALS_POP (); 12072 PUSH_X (); 12073 PUSH_X (); 12074 break; 12075 12076 case ROT: 12077 Y_EQUALS_POP (); 12078 X_EQUALS_POP (); 12079 PUSH_Y (); 12080 PUSH_X (); 12081 break; 12082 12083 case BINARY_ADD: 12084 Y_EQUALS_POP (); 12085 X_EQUALS_POP (); 12086 PUSH_RVALUE ( 12087 ctxt.new_binary_op ( 12088 GCC_JIT_BINARY_OP_PLUS, 12089 int_type, 12090 x, y, 12091 loc)); 12092 break; 12093 12094 case BINARY_SUBTRACT: 12095 Y_EQUALS_POP (); 12096 X_EQUALS_POP (); 12097 PUSH_RVALUE ( 12098 ctxt.new_binary_op ( 12099 GCC_JIT_BINARY_OP_MINUS, 12100 int_type, 12101 x, y, 12102 loc)); 12103 break; 12104 12105 case BINARY_MULT: 12106 Y_EQUALS_POP (); 12107 X_EQUALS_POP (); 12108 PUSH_RVALUE ( 12109 ctxt.new_binary_op ( 12110 GCC_JIT_BINARY_OP_MULT, 12111 int_type, 12112 x, y, 12113 loc)); 12114 break; 12115 12116 case BINARY_COMPARE_LT: 12117 Y_EQUALS_POP (); 12118 X_EQUALS_POP (); 12119 PUSH_RVALUE ( 12120 /* cast of bool to int */ 12121 ctxt.new_cast ( 12122 /* (x < y) as a bool */ 12123 ctxt.new_comparison ( 12124 GCC_JIT_COMPARISON_LT, 12125 x, y, 12126 loc), 12127 int_type, 12128 loc)); 12129 break; 12130 12131 case RECURSE: 12132 @{ 12133 X_EQUALS_POP (); 12134 PUSH_RVALUE ( 12135 ctxt.new_call ( 12136 fn, 12137 x, 12138 loc)); 12139 break; 12140 @} 12141 12142 case RETURN: 12143 X_EQUALS_POP (); 12144 block.end_with_return (x, loc); 12145 break; 12146 12147 /* Ops taking an operand. */ 12148 case PUSH_CONST: 12149 PUSH_RVALUE ( 12150 ctxt.new_rvalue (int_type, op->op_operand)); 12151 break; 12152 12153 case JUMP_ABS_IF_TRUE: 12154 X_EQUALS_POP (); 12155 block.end_with_conditional ( 12156 /* "(bool)x". */ 12157 ctxt.new_cast (x, bool_type, loc), 12158 op_blocks[op->op_operand], /* on_true */ 12159 next_block, /* on_false */ 12160 loc); 12161 break; 12162 12163 default: 12164 assert(0); 12165 @} /* end of switch on opcode */ 12166 12167 @end example 12168 @end quotation 12169 12170 Every block must be terminated, via a call to one of the 12171 @code{gccjit::block::end_with_} entrypoints. This has been done for two 12172 of the opcodes, but we need to do it for the other ones, by jumping 12173 to the next block. 12174 12175 @quotation 12176 12177 @example 12178 if (op->op_opcode != JUMP_ABS_IF_TRUE 12179 && op->op_opcode != RETURN) 12180 block.end_with_jump (next_block, loc); 12181 12182 @end example 12183 @end quotation 12184 12185 This is analogous to simply incrementing the program counter. 12186 12187 @node Verifying the control flow graph<2>,Compiling the context<2>,Populating the function<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12188 @anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{19e} 12189 @subsubsection Verifying the control flow graph 12190 12191 12192 Having finished looping over the blocks, the context is complete. 12193 12194 As before, we can verify that the control flow and statements are sane by 12195 using @ref{194,,gccjit;;function;;dump_to_dot()}: 12196 12197 @example 12198 fn.dump_to_dot ("/tmp/factorial.dot"); 12199 @end example 12200 12201 and viewing the result. Note how the label names, comments, and 12202 variable names show up in the dump, to make it easier to spot 12203 errors in our compiler. 12204 12205 @quotation 12206 12207 12208 @float Figure 12209 12210 @image{libgccjit-figures/factorial,,,image of a control flow graph,png} 12211 12212 @end float 12213 12214 @end quotation 12215 12216 @node Compiling the context<2>,Single-stepping through the generated code<2>,Verifying the control flow graph<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12217 @anchor{cp/intro/tutorial04 compiling-the-context}@anchor{19f} 12218 @subsubsection Compiling the context 12219 12220 12221 Having finished looping over the blocks and populating them with 12222 statements, the context is complete. 12223 12224 We can now compile it, extract machine code from the result, and 12225 run it: 12226 12227 @quotation 12228 12229 @example 12230 12231 class compilation_result 12232 @{ 12233 public: 12234 compilation_result (gcc_jit_result *result) : 12235 m_result (result) 12236 @{ 12237 @} 12238 ~compilation_result () 12239 @{ 12240 gcc_jit_result_release (m_result); 12241 @} 12242 12243 void *get_code (const char *funcname) 12244 @{ 12245 return gcc_jit_result_get_code (m_result, funcname); 12246 @} 12247 12248 private: 12249 gcc_jit_result *m_result; 12250 @}; 12251 12252 @end example 12253 12254 @example 12255 compilation_result compiler_result = fn->compile (); 12256 12257 const char *funcname = fn->get_function_name (); 12258 toyvm_compiled_func code 12259 = (toyvm_compiled_func)compiler_result.get_code (funcname); 12260 12261 printf ("compiler result: %d\n", 12262 code (atoi (argv[2]))); 12263 12264 @end example 12265 @end quotation 12266 12267 @node Single-stepping through the generated code<2>,Examining the generated code<2>,Compiling the context<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12268 @anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{1a0} 12269 @subsubsection Single-stepping through the generated code 12270 12271 12272 Its possible to debug the generated code. To do this we need to both: 12273 12274 @quotation 12275 12276 12277 @itemize * 12278 12279 @item 12280 Set up source code locations for our statements, so that we can 12281 meaningfully step through the code. We did this above by 12282 calling @ref{1a1,,gccjit;;context;;new_location()} and using the 12283 results. 12284 12285 @item 12286 Enable the generation of debugging information, by setting 12287 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 12288 @ref{175,,gccjit;;context} via 12289 @ref{181,,gccjit;;context;;set_bool_option()}: 12290 12291 @example 12292 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); 12293 @end example 12294 @end itemize 12295 @end quotation 12296 12297 Having done this, we can put a breakpoint on the generated function: 12298 12299 @example 12300 $ gdb --args ./toyvm factorial.toy 10 12301 (gdb) break factorial 12302 Function "factorial" not defined. 12303 Make breakpoint pending on future shared library load? (y or [n]) y 12304 Breakpoint 1 (factorial) pending. 12305 (gdb) run 12306 Breakpoint 1, factorial (arg=10) at factorial.toy:14 12307 14 DUP 12308 @end example 12309 12310 Weve set up location information, which references @code{factorial.toy}. 12311 This allows us to use e.g. @code{list} to see where we are in the script: 12312 12313 @example 12314 (gdb) list 12315 9 12316 10 # Initial state: 12317 11 # stack: [arg] 12318 12 12319 13 # 0: 12320 14 DUP 12321 15 # stack: [arg, arg] 12322 16 12323 17 # 1: 12324 18 PUSH_CONST 2 12325 @end example 12326 12327 and to step through the function, examining the data: 12328 12329 @example 12330 (gdb) n 12331 18 PUSH_CONST 2 12332 (gdb) n 12333 22 BINARY_COMPARE_LT 12334 (gdb) print stack 12335 $5 = @{10, 10, 2, 0, -7152, 32767, 0, 0@} 12336 (gdb) print stack_depth 12337 $6 = 3 12338 @end example 12339 12340 Youll see that the parts of the @code{stack} array that havent been 12341 touched yet are uninitialized. 12342 12343 @cartouche 12344 @quotation Note 12345 Turning on optimizations may lead to unpredictable results when 12346 stepping through the generated code: the execution may appear to 12347 jump around the source code. This is analogous to turning up the 12348 optimization level in a regular compiler. 12349 @end quotation 12350 @end cartouche 12351 12352 @node Examining the generated code<2>,Putting it all together<2>,Single-stepping through the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12353 @anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{1a2} 12354 @subsubsection Examining the generated code 12355 12356 12357 How good is the optimized code? 12358 12359 We can turn up optimizations, by calling 12360 @ref{182,,gccjit;;context;;set_int_option()} with 12361 @ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 12362 12363 @example 12364 ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); 12365 @end example 12366 12367 One of GCCs internal representations is called gimple. A dump of the 12368 initial gimple representation of the code can be seen by setting: 12369 12370 @example 12371 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); 12372 @end example 12373 12374 With optimization on and source locations displayed, this gives: 12375 12376 @c We'll use "c" for gimple dumps 12377 12378 @example 12379 factorial (signed int arg) 12380 @{ 12381 <unnamed type> D.80; 12382 signed int D.81; 12383 signed int D.82; 12384 signed int D.83; 12385 signed int D.84; 12386 signed int D.85; 12387 signed int y; 12388 signed int x; 12389 signed int stack_depth; 12390 signed int stack[8]; 12391 12392 try 12393 @{ 12394 initial: 12395 stack_depth = 0; 12396 stack[stack_depth] = arg; 12397 stack_depth = stack_depth + 1; 12398 goto instr0; 12399 instr0: 12400 /* DUP */: 12401 stack_depth = stack_depth + -1; 12402 x = stack[stack_depth]; 12403 stack[stack_depth] = x; 12404 stack_depth = stack_depth + 1; 12405 stack[stack_depth] = x; 12406 stack_depth = stack_depth + 1; 12407 goto instr1; 12408 instr1: 12409 /* PUSH_CONST */: 12410 stack[stack_depth] = 2; 12411 stack_depth = stack_depth + 1; 12412 goto instr2; 12413 12414 /* etc */ 12415 @end example 12416 12417 You can see the generated machine code in assembly form via: 12418 12419 @example 12420 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1); 12421 result = ctxt.compile (); 12422 @end example 12423 12424 which shows that (on this x86_64 box) the compiler has unrolled the loop 12425 and is using MMX instructions to perform several multiplications 12426 simultaneously: 12427 12428 @example 12429 .file "fake.c" 12430 .text 12431 .Ltext0: 12432 .p2align 4,,15 12433 .globl factorial 12434 .type factorial, @@function 12435 factorial: 12436 .LFB0: 12437 .file 1 "factorial.toy" 12438 .loc 1 14 0 12439 .cfi_startproc 12440 .LVL0: 12441 .L2: 12442 .loc 1 26 0 12443 cmpl $1, %edi 12444 jle .L13 12445 leal -1(%rdi), %edx 12446 movl %edx, %ecx 12447 shrl $2, %ecx 12448 leal 0(,%rcx,4), %esi 12449 testl %esi, %esi 12450 je .L14 12451 cmpl $9, %edx 12452 jbe .L14 12453 leal -2(%rdi), %eax 12454 movl %eax, -16(%rsp) 12455 leal -3(%rdi), %eax 12456 movd -16(%rsp), %xmm0 12457 movl %edi, -16(%rsp) 12458 movl %eax, -12(%rsp) 12459 movd -16(%rsp), %xmm1 12460 xorl %eax, %eax 12461 movl %edx, -16(%rsp) 12462 movd -12(%rsp), %xmm4 12463 movd -16(%rsp), %xmm6 12464 punpckldq %xmm4, %xmm0 12465 movdqa .LC1(%rip), %xmm4 12466 punpckldq %xmm6, %xmm1 12467 punpcklqdq %xmm0, %xmm1 12468 movdqa .LC0(%rip), %xmm0 12469 jmp .L5 12470 # etc - edited for brevity 12471 @end example 12472 12473 This is clearly overkill for a function that will likely overflow the 12474 @code{int} type before the vectorization is worthwhile - but then again, this 12475 is a toy example. 12476 12477 Turning down the optimization level to 2: 12478 12479 @example 12480 ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2); 12481 @end example 12482 12483 yields this code, which is simple enough to quote in its entirety: 12484 12485 @example 12486 .file "fake.c" 12487 .text 12488 .p2align 4,,15 12489 .globl factorial 12490 .type factorial, @@function 12491 factorial: 12492 .LFB0: 12493 .cfi_startproc 12494 .L2: 12495 cmpl $1, %edi 12496 jle .L8 12497 movl $1, %edx 12498 jmp .L4 12499 .p2align 4,,10 12500 .p2align 3 12501 .L6: 12502 movl %eax, %edi 12503 .L4: 12504 .L5: 12505 leal -1(%rdi), %eax 12506 imull %edi, %edx 12507 cmpl $1, %eax 12508 jne .L6 12509 .L3: 12510 .L7: 12511 imull %edx, %eax 12512 ret 12513 .L8: 12514 movl %edi, %eax 12515 movl $1, %edx 12516 jmp .L7 12517 .cfi_endproc 12518 .LFE0: 12519 .size factorial, .-factorial 12520 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%@{gcc_release@})" 12521 .section .note.GNU-stack,"",@@progbits 12522 @end example 12523 12524 Note that the stack pushing and popping have been eliminated, as has the 12525 recursive call (in favor of an iteration). 12526 12527 @node Putting it all together<2>,Behind the curtain How does our code get optimized?<2>,Examining the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12528 @anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{1a3} 12529 @subsubsection Putting it all together 12530 12531 12532 The complete example can be seen in the source tree at 12533 @code{gcc/jit/docs/examples/tut04-toyvm/toyvm.cc} 12534 12535 along with a Makefile and a couple of sample .toy scripts: 12536 12537 @example 12538 $ ls -al 12539 drwxrwxr-x. 2 david david 4096 Sep 19 17:46 . 12540 drwxrwxr-x. 3 david david 4096 Sep 19 15:26 .. 12541 -rw-rw-r--. 1 david david 615 Sep 19 12:43 factorial.toy 12542 -rw-rw-r--. 1 david david 834 Sep 19 13:08 fibonacci.toy 12543 -rw-rw-r--. 1 david david 238 Sep 19 14:22 Makefile 12544 -rw-rw-r--. 1 david david 16457 Sep 19 17:07 toyvm.cc 12545 12546 $ make toyvm 12547 g++ -Wall -g -o toyvm toyvm.cc -lgccjit 12548 12549 $ ./toyvm factorial.toy 10 12550 interpreter result: 3628800 12551 compiler result: 3628800 12552 12553 $ ./toyvm fibonacci.toy 10 12554 interpreter result: 55 12555 compiler result: 55 12556 @end example 12557 12558 @node Behind the curtain How does our code get optimized?<2>,,Putting it all together<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 12559 @anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{1a4} 12560 @subsubsection Behind the curtain: How does our code get optimized? 12561 12562 12563 Our example is done, but you may be wondering about exactly how the 12564 compiler turned what we gave it into the machine code seen above. 12565 12566 We can examine what the compiler is doing in detail by setting: 12567 12568 @example 12569 state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 1); 12570 state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 1); 12571 @end example 12572 12573 This will dump detailed information about the compilers state to a 12574 directory under @code{/tmp}, and keep it from being cleaned up. 12575 12576 The precise names and their formats of these files is subject to change. 12577 Higher optimization levels lead to more files. 12578 Heres what I saw (edited for brevity; there were almost 200 files): 12579 12580 @example 12581 intermediate files written to /tmp/libgccjit-KPQbGw 12582 $ ls /tmp/libgccjit-KPQbGw/ 12583 fake.c.000i.cgraph 12584 fake.c.000i.type-inheritance 12585 fake.c.004t.gimple 12586 fake.c.007t.omplower 12587 fake.c.008t.lower 12588 fake.c.011t.eh 12589 fake.c.012t.cfg 12590 fake.c.014i.visibility 12591 fake.c.015i.early_local_cleanups 12592 fake.c.016t.ssa 12593 # etc 12594 @end example 12595 12596 The gimple code is converted into Static Single Assignment form, 12597 with annotations for use when generating the debuginfo: 12598 12599 @example 12600 $ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa 12601 @end example 12602 12603 @example 12604 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12605 12606 factorial (signed int arg) 12607 @{ 12608 signed int stack[8]; 12609 signed int stack_depth; 12610 signed int x; 12611 signed int y; 12612 <unnamed type> _20; 12613 signed int _21; 12614 signed int _38; 12615 signed int _44; 12616 signed int _51; 12617 signed int _56; 12618 12619 initial: 12620 stack_depth_3 = 0; 12621 # DEBUG stack_depth => stack_depth_3 12622 stack[stack_depth_3] = arg_5(D); 12623 stack_depth_7 = stack_depth_3 + 1; 12624 # DEBUG stack_depth => stack_depth_7 12625 # DEBUG instr0 => NULL 12626 # DEBUG /* DUP */ => NULL 12627 stack_depth_8 = stack_depth_7 + -1; 12628 # DEBUG stack_depth => stack_depth_8 12629 x_9 = stack[stack_depth_8]; 12630 # DEBUG x => x_9 12631 stack[stack_depth_8] = x_9; 12632 stack_depth_11 = stack_depth_8 + 1; 12633 # DEBUG stack_depth => stack_depth_11 12634 stack[stack_depth_11] = x_9; 12635 stack_depth_13 = stack_depth_11 + 1; 12636 # DEBUG stack_depth => stack_depth_13 12637 # DEBUG instr1 => NULL 12638 # DEBUG /* PUSH_CONST */ => NULL 12639 stack[stack_depth_13] = 2; 12640 12641 /* etc; edited for brevity */ 12642 @end example 12643 12644 We can perhaps better see the code by turning off 12645 @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to suppress all those @code{DEBUG} 12646 statements, giving: 12647 12648 @example 12649 $ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa 12650 @end example 12651 12652 @example 12653 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12654 12655 factorial (signed int arg) 12656 @{ 12657 signed int stack[8]; 12658 signed int stack_depth; 12659 signed int x; 12660 signed int y; 12661 <unnamed type> _20; 12662 signed int _21; 12663 signed int _38; 12664 signed int _44; 12665 signed int _51; 12666 signed int _56; 12667 12668 initial: 12669 stack_depth_3 = 0; 12670 stack[stack_depth_3] = arg_5(D); 12671 stack_depth_7 = stack_depth_3 + 1; 12672 stack_depth_8 = stack_depth_7 + -1; 12673 x_9 = stack[stack_depth_8]; 12674 stack[stack_depth_8] = x_9; 12675 stack_depth_11 = stack_depth_8 + 1; 12676 stack[stack_depth_11] = x_9; 12677 stack_depth_13 = stack_depth_11 + 1; 12678 stack[stack_depth_13] = 2; 12679 stack_depth_15 = stack_depth_13 + 1; 12680 stack_depth_16 = stack_depth_15 + -1; 12681 y_17 = stack[stack_depth_16]; 12682 stack_depth_18 = stack_depth_16 + -1; 12683 x_19 = stack[stack_depth_18]; 12684 _20 = x_19 < y_17; 12685 _21 = (signed int) _20; 12686 stack[stack_depth_18] = _21; 12687 stack_depth_23 = stack_depth_18 + 1; 12688 stack_depth_24 = stack_depth_23 + -1; 12689 x_25 = stack[stack_depth_24]; 12690 if (x_25 != 0) 12691 goto <bb 4> (instr9); 12692 else 12693 goto <bb 3> (instr4); 12694 12695 instr4: 12696 /* DUP */: 12697 stack_depth_26 = stack_depth_24 + -1; 12698 x_27 = stack[stack_depth_26]; 12699 stack[stack_depth_26] = x_27; 12700 stack_depth_29 = stack_depth_26 + 1; 12701 stack[stack_depth_29] = x_27; 12702 stack_depth_31 = stack_depth_29 + 1; 12703 stack[stack_depth_31] = 1; 12704 stack_depth_33 = stack_depth_31 + 1; 12705 stack_depth_34 = stack_depth_33 + -1; 12706 y_35 = stack[stack_depth_34]; 12707 stack_depth_36 = stack_depth_34 + -1; 12708 x_37 = stack[stack_depth_36]; 12709 _38 = x_37 - y_35; 12710 stack[stack_depth_36] = _38; 12711 stack_depth_40 = stack_depth_36 + 1; 12712 stack_depth_41 = stack_depth_40 + -1; 12713 x_42 = stack[stack_depth_41]; 12714 _44 = factorial (x_42); 12715 stack[stack_depth_41] = _44; 12716 stack_depth_46 = stack_depth_41 + 1; 12717 stack_depth_47 = stack_depth_46 + -1; 12718 y_48 = stack[stack_depth_47]; 12719 stack_depth_49 = stack_depth_47 + -1; 12720 x_50 = stack[stack_depth_49]; 12721 _51 = x_50 * y_48; 12722 stack[stack_depth_49] = _51; 12723 stack_depth_53 = stack_depth_49 + 1; 12724 12725 # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)> 12726 instr9: 12727 /* RETURN */: 12728 stack_depth_54 = stack_depth_1 + -1; 12729 x_55 = stack[stack_depth_54]; 12730 _56 = x_55; 12731 stack =@{v@} @{CLOBBER@}; 12732 return _56; 12733 12734 @} 12735 @end example 12736 12737 Note in the above how all the @ref{18b,,gccjit;;block} instances we 12738 created have been consolidated into just 3 blocks in GCCs internal 12739 representation: @code{initial}, @code{instr4} and @code{instr9}. 12740 12741 @menu 12742 * Optimizing away stack manipulation: Optimizing away stack manipulation<2>. 12743 * Elimination of tail recursion: Elimination of tail recursion<2>. 12744 12745 @end menu 12746 12747 @node Optimizing away stack manipulation<2>,Elimination of tail recursion<2>,,Behind the curtain How does our code get optimized?<2> 12748 @anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{1a5} 12749 @subsubsection Optimizing away stack manipulation 12750 12751 12752 Recall our simple implementation of stack operations. Lets examine 12753 how the stack operations are optimized away. 12754 12755 After a pass of constant-propagation, the depth of the stack at each 12756 opcode can be determined at compile-time: 12757 12758 @example 12759 $ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1 12760 @end example 12761 12762 @example 12763 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12764 12765 factorial (signed int arg) 12766 @{ 12767 signed int stack[8]; 12768 signed int stack_depth; 12769 signed int x; 12770 signed int y; 12771 <unnamed type> _20; 12772 signed int _21; 12773 signed int _38; 12774 signed int _44; 12775 signed int _51; 12776 12777 initial: 12778 stack[0] = arg_5(D); 12779 x_9 = stack[0]; 12780 stack[0] = x_9; 12781 stack[1] = x_9; 12782 stack[2] = 2; 12783 y_17 = stack[2]; 12784 x_19 = stack[1]; 12785 _20 = x_19 < y_17; 12786 _21 = (signed int) _20; 12787 stack[1] = _21; 12788 x_25 = stack[1]; 12789 if (x_25 != 0) 12790 goto <bb 4> (instr9); 12791 else 12792 goto <bb 3> (instr4); 12793 12794 instr4: 12795 /* DUP */: 12796 x_27 = stack[0]; 12797 stack[0] = x_27; 12798 stack[1] = x_27; 12799 stack[2] = 1; 12800 y_35 = stack[2]; 12801 x_37 = stack[1]; 12802 _38 = x_37 - y_35; 12803 stack[1] = _38; 12804 x_42 = stack[1]; 12805 _44 = factorial (x_42); 12806 stack[1] = _44; 12807 y_48 = stack[1]; 12808 x_50 = stack[0]; 12809 _51 = x_50 * y_48; 12810 stack[0] = _51; 12811 12812 instr9: 12813 /* RETURN */: 12814 x_55 = stack[0]; 12815 x_56 = x_55; 12816 stack =@{v@} @{CLOBBER@}; 12817 return x_56; 12818 12819 @} 12820 @end example 12821 12822 Note how, in the above, all those @code{stack_depth} values are now just 12823 constants: were accessing specific stack locations at each opcode. 12824 12825 The esra pass (Early Scalar Replacement of Aggregates) breaks 12826 out our stack array into individual elements: 12827 12828 @example 12829 $ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra 12830 @end example 12831 12832 @example 12833 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12834 12835 Created a replacement for stack offset: 0, size: 32: stack$0 12836 Created a replacement for stack offset: 32, size: 32: stack$1 12837 Created a replacement for stack offset: 64, size: 32: stack$2 12838 12839 Symbols to be put in SSA form 12840 @{ D.89 D.90 D.91 @} 12841 Incremental SSA update started at block: 0 12842 Number of blocks in CFG: 5 12843 Number of blocks to update: 4 ( 80%) 12844 12845 12846 factorial (signed int arg) 12847 @{ 12848 signed int stack$2; 12849 signed int stack$1; 12850 signed int stack$0; 12851 signed int stack[8]; 12852 signed int stack_depth; 12853 signed int x; 12854 signed int y; 12855 <unnamed type> _20; 12856 signed int _21; 12857 signed int _38; 12858 signed int _44; 12859 signed int _51; 12860 12861 initial: 12862 stack$0_45 = arg_5(D); 12863 x_9 = stack$0_45; 12864 stack$0_39 = x_9; 12865 stack$1_32 = x_9; 12866 stack$2_30 = 2; 12867 y_17 = stack$2_30; 12868 x_19 = stack$1_32; 12869 _20 = x_19 < y_17; 12870 _21 = (signed int) _20; 12871 stack$1_28 = _21; 12872 x_25 = stack$1_28; 12873 if (x_25 != 0) 12874 goto <bb 4> (instr9); 12875 else 12876 goto <bb 3> (instr4); 12877 12878 instr4: 12879 /* DUP */: 12880 x_27 = stack$0_39; 12881 stack$0_22 = x_27; 12882 stack$1_14 = x_27; 12883 stack$2_12 = 1; 12884 y_35 = stack$2_12; 12885 x_37 = stack$1_14; 12886 _38 = x_37 - y_35; 12887 stack$1_10 = _38; 12888 x_42 = stack$1_10; 12889 _44 = factorial (x_42); 12890 stack$1_6 = _44; 12891 y_48 = stack$1_6; 12892 x_50 = stack$0_22; 12893 _51 = x_50 * y_48; 12894 stack$0_1 = _51; 12895 12896 # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)> 12897 instr9: 12898 /* RETURN */: 12899 x_55 = stack$0_52; 12900 x_56 = x_55; 12901 stack =@{v@} @{CLOBBER@}; 12902 return x_56; 12903 12904 @} 12905 @end example 12906 12907 Hence at this point, all those pushes and pops of the stack are now 12908 simply assignments to specific temporary variables. 12909 12910 After some copy propagation, the stack manipulation has been completely 12911 optimized away: 12912 12913 @example 12914 $ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1 12915 @end example 12916 12917 @example 12918 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12919 12920 factorial (signed int arg) 12921 @{ 12922 signed int stack$2; 12923 signed int stack$1; 12924 signed int stack$0; 12925 signed int stack[8]; 12926 signed int stack_depth; 12927 signed int x; 12928 signed int y; 12929 <unnamed type> _20; 12930 signed int _21; 12931 signed int _38; 12932 signed int _44; 12933 signed int _51; 12934 12935 initial: 12936 stack$0_39 = arg_5(D); 12937 _20 = arg_5(D) <= 1; 12938 _21 = (signed int) _20; 12939 if (_21 != 0) 12940 goto <bb 4> (instr9); 12941 else 12942 goto <bb 3> (instr4); 12943 12944 instr4: 12945 /* DUP */: 12946 _38 = arg_5(D) + -1; 12947 _44 = factorial (_38); 12948 _51 = arg_5(D) * _44; 12949 stack$0_1 = _51; 12950 12951 # stack$0_52 = PHI <arg_5(D)(2), _51(3)> 12952 instr9: 12953 /* RETURN */: 12954 stack =@{v@} @{CLOBBER@}; 12955 return stack$0_52; 12956 12957 @} 12958 @end example 12959 12960 Later on, another pass finally eliminated @code{stack_depth} local and the 12961 unused parts of the @cite{stack`} array altogether: 12962 12963 @example 12964 $ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa 12965 @end example 12966 12967 @example 12968 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12969 12970 Released 44 names, 314.29%, removed 44 holes 12971 factorial (signed int arg) 12972 @{ 12973 signed int stack$0; 12974 signed int mult_acc_1; 12975 <unnamed type> _5; 12976 signed int _6; 12977 signed int _7; 12978 signed int mul_tmp_10; 12979 signed int mult_acc_11; 12980 signed int mult_acc_13; 12981 12982 # arg_9 = PHI <arg_8(D)(0)> 12983 # mult_acc_13 = PHI <1(0)> 12984 initial: 12985 12986 <bb 5>: 12987 # arg_4 = PHI <arg_9(2), _7(3)> 12988 # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)> 12989 _5 = arg_4 <= 1; 12990 _6 = (signed int) _5; 12991 if (_6 != 0) 12992 goto <bb 4> (instr9); 12993 else 12994 goto <bb 3> (instr4); 12995 12996 instr4: 12997 /* DUP */: 12998 _7 = arg_4 + -1; 12999 mult_acc_11 = mult_acc_1 * arg_4; 13000 goto <bb 5>; 13001 13002 # stack$0_12 = PHI <arg_4(5)> 13003 instr9: 13004 /* RETURN */: 13005 mul_tmp_10 = mult_acc_1 * stack$0_12; 13006 return mul_tmp_10; 13007 13008 @} 13009 @end example 13010 13011 @node Elimination of tail recursion<2>,,Optimizing away stack manipulation<2>,Behind the curtain How does our code get optimized?<2> 13012 @anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{1a6} 13013 @subsubsection Elimination of tail recursion 13014 13015 13016 Another significant optimization is the detection that the call to 13017 @code{factorial} is tail recursion, which can be eliminated in favor of 13018 an iteration: 13019 13020 @example 13021 $ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1 13022 @end example 13023 13024 @example 13025 ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 13026 13027 13028 Symbols to be put in SSA form 13029 @{ D.88 @} 13030 Incremental SSA update started at block: 0 13031 Number of blocks in CFG: 5 13032 Number of blocks to update: 4 ( 80%) 13033 13034 13035 factorial (signed int arg) 13036 @{ 13037 signed int stack$2; 13038 signed int stack$1; 13039 signed int stack$0; 13040 signed int stack[8]; 13041 signed int stack_depth; 13042 signed int x; 13043 signed int y; 13044 signed int mult_acc_1; 13045 <unnamed type> _20; 13046 signed int _21; 13047 signed int _38; 13048 signed int mul_tmp_44; 13049 signed int mult_acc_51; 13050 13051 # arg_5 = PHI <arg_39(D)(0), _38(3)> 13052 # mult_acc_1 = PHI <1(0), mult_acc_51(3)> 13053 initial: 13054 _20 = arg_5 <= 1; 13055 _21 = (signed int) _20; 13056 if (_21 != 0) 13057 goto <bb 4> (instr9); 13058 else 13059 goto <bb 3> (instr4); 13060 13061 instr4: 13062 /* DUP */: 13063 _38 = arg_5 + -1; 13064 mult_acc_51 = mult_acc_1 * arg_5; 13065 goto <bb 2> (initial); 13066 13067 # stack$0_52 = PHI <arg_5(2)> 13068 instr9: 13069 /* RETURN */: 13070 stack =@{v@} @{CLOBBER@}; 13071 mul_tmp_44 = mult_acc_1 * stack$0_52; 13072 return mul_tmp_44; 13073 13074 @} 13075 @end example 13076 13077 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 13078 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 13079 @c 13080 @c This is free software: you can redistribute it and/or modify it 13081 @c under the terms of the GNU General Public License as published by 13082 @c the Free Software Foundation, either version 3 of the License, or 13083 @c (at your option) any later version. 13084 @c 13085 @c This program is distributed in the hope that it will be useful, but 13086 @c WITHOUT ANY WARRANTY; without even the implied warranty of 13087 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13088 @c General Public License for more details. 13089 @c 13090 @c You should have received a copy of the GNU General Public License 13091 @c along with this program. If not, see 13092 @c <https://www.gnu.org/licenses/>. 13093 13094 @node Topic Reference<2>,,Tutorial<2>,C++ bindings for libgccjit 13095 @anchor{cp/topics/index doc}@anchor{1a7}@anchor{cp/topics/index topic-reference}@anchor{1a8} 13096 @section Topic Reference 13097 13098 13099 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 13100 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 13101 @c 13102 @c This is free software: you can redistribute it and/or modify it 13103 @c under the terms of the GNU General Public License as published by 13104 @c the Free Software Foundation, either version 3 of the License, or 13105 @c (at your option) any later version. 13106 @c 13107 @c This program is distributed in the hope that it will be useful, but 13108 @c WITHOUT ANY WARRANTY; without even the implied warranty of 13109 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13110 @c General Public License for more details. 13111 @c 13112 @c You should have received a copy of the GNU General Public License 13113 @c along with this program. If not, see 13114 @c <https://www.gnu.org/licenses/>. 13115 13116 @menu 13117 * Compilation contexts: Compilation contexts<2>. 13118 * Objects: Objects<2>. 13119 * Types: Types<2>. 13120 * Expressions: Expressions<2>. 13121 * Creating and using functions: Creating and using functions<2>. 13122 * Source Locations: Source Locations<2>. 13123 * Compiling a context: Compiling a context<2>. 13124 * Using Assembly Language with libgccjit++:: 13125 13126 @end menu 13127 13128 @node Compilation contexts<2>,Objects<2>,,Topic Reference<2> 13129 @anchor{cp/topics/contexts doc}@anchor{1a9}@anchor{cp/topics/contexts compilation-contexts}@anchor{1aa} 13130 @subsection Compilation contexts 13131 13132 13133 @geindex gccjit;;context (C++ class) 13134 @anchor{cp/topics/contexts _CPPv4N6gccjit7contextE}@anchor{175}@anchor{cp/topics/contexts _CPPv3N6gccjit7contextE}@anchor{1ab}@anchor{cp/topics/contexts _CPPv2N6gccjit7contextE}@anchor{1ac}@anchor{cp/topics/contexts gccjit context}@anchor{1ad} 13135 @deffn {C++ Class} gccjit::context 13136 @end deffn 13137 13138 The top-level of the C++ API is the @ref{175,,gccjit;;context} type. 13139 13140 A @ref{175,,gccjit;;context} instance encapsulates the state of a 13141 compilation. 13142 13143 You can set up options on it, and add types, functions and code. 13144 Invoking @ref{17f,,gccjit;;context;;compile()} on it gives you a 13145 @ref{16,,gcc_jit_result *}. 13146 13147 It is a thin wrapper around the C APIs @ref{8,,gcc_jit_context *}. 13148 13149 @menu 13150 * Lifetime-management: Lifetime-management<2>. 13151 * Thread-safety: Thread-safety<2>. 13152 * Error-handling: Error-handling<3>. 13153 * Debugging: Debugging<2>. 13154 * Options: Options<4>. 13155 13156 @end menu 13157 13158 @node Lifetime-management<2>,Thread-safety<2>,,Compilation contexts<2> 13159 @anchor{cp/topics/contexts lifetime-management}@anchor{1ae} 13160 @subsubsection Lifetime-management 13161 13162 13163 Contexts are the unit of lifetime-management within the API: objects 13164 have their lifetime bounded by the context they are created within, and 13165 cleanup of such objects is done for you when the context is released. 13166 13167 @geindex gccjit;;context;;acquire (C++ function) 13168 @anchor{cp/topics/contexts _CPPv4N6gccjit7context7acquireEv}@anchor{176}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7acquireEv}@anchor{1af}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7acquireEv}@anchor{1b0}@anchor{cp/topics/contexts gccjit context acquire}@anchor{1b1} 13169 @deffn {C++ Function} gccjit::@ref{175,,context} gccjit::@ref{175,,context}::acquire () 13170 13171 This function acquires a new @ref{175,,gccjit;;context} instance, 13172 which is independent of any others that may be present within this 13173 process. 13174 @end deffn 13175 13176 @geindex gccjit;;context;;release (C++ function) 13177 @anchor{cp/topics/contexts _CPPv4N6gccjit7context7releaseEv}@anchor{179}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7releaseEv}@anchor{1b2}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7releaseEv}@anchor{1b3}@anchor{cp/topics/contexts gccjit context release}@anchor{1b4} 13178 @deffn {C++ Function} void gccjit::@ref{175,,context}::release () 13179 13180 This function releases all resources associated with the given context. 13181 Both the context itself and all of its @code{gccjit::object *} 13182 instances are cleaned up. It should be called exactly once on a given 13183 context. 13184 13185 It is invalid to use the context or any of its contextual objects 13186 after calling this. 13187 13188 @example 13189 ctxt.release (); 13190 @end example 13191 @end deffn 13192 13193 @geindex gccjit;;context;;new_child_context (C++ function) 13194 @anchor{cp/topics/contexts _CPPv4N6gccjit7context17new_child_contextEv}@anchor{1b5}@anchor{cp/topics/contexts _CPPv3N6gccjit7context17new_child_contextEv}@anchor{1b6}@anchor{cp/topics/contexts _CPPv2N6gccjit7context17new_child_contextEv}@anchor{1b7}@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{1b8} 13195 @deffn {C++ Function} gccjit::@ref{175,,context} gccjit::@ref{175,,context}::new_child_context () 13196 13197 Given an existing JIT context, create a child context. 13198 13199 The child inherits a copy of all option-settings from the parent. 13200 13201 The child can reference objects created within the parent, but not 13202 vice-versa. 13203 13204 The lifetime of the child context must be bounded by that of the 13205 parent: you should release a child context before releasing the parent 13206 context. 13207 13208 If you use a function from a parent context within a child context, 13209 you have to compile the parent context before you can compile the 13210 child context, and the gccjit::result of the parent context must 13211 outlive the gccjit::result of the child context. 13212 13213 This allows caching of shared initializations. For example, you could 13214 create types and declarations of global functions in a parent context 13215 once within a process, and then create child contexts whenever a 13216 function or loop becomes hot. Each such child context can be used for 13217 JIT-compiling just one function or loop, but can reference types 13218 and helper functions created within the parent context. 13219 13220 Contexts can be arbitrarily nested, provided the above rules are 13221 followed, but its probably not worth going above 2 or 3 levels, and 13222 there will likely be a performance hit for such nesting. 13223 @end deffn 13224 13225 @node Thread-safety<2>,Error-handling<3>,Lifetime-management<2>,Compilation contexts<2> 13226 @anchor{cp/topics/contexts thread-safety}@anchor{1b9} 13227 @subsubsection Thread-safety 13228 13229 13230 Instances of @ref{175,,gccjit;;context} created via 13231 @ref{176,,gccjit;;context;;acquire()} are independent from each other: 13232 only one thread may use a given context at once, but multiple threads 13233 could each have their own contexts without needing locks. 13234 13235 Contexts created via @ref{1b5,,gccjit;;context;;new_child_context()} are 13236 related to their parent context. They can be partitioned by their 13237 ultimate ancestor into independent family trees. Only one thread 13238 within a process may use a given family tree of such contexts at once, 13239 and if youre using multiple threads you should provide your own locking 13240 around entire such context partitions. 13241 13242 @node Error-handling<3>,Debugging<2>,Thread-safety<2>,Compilation contexts<2> 13243 @anchor{cp/topics/contexts error-handling}@anchor{1ba} 13244 @subsubsection Error-handling 13245 13246 13247 @c FIXME: How does error-handling work for C++ API? 13248 13249 You can only compile and get code from a context if no errors occur. 13250 13251 In general, if an error occurs when using an API entrypoint, it returns 13252 NULL. You dont have to check everywhere for NULL results, since the 13253 API gracefully handles a NULL being passed in for any argument. 13254 13255 Errors are printed on stderr and can be queried using 13256 @ref{1bb,,gccjit;;context;;get_first_error()}. 13257 13258 @geindex gccjit;;context;;get_first_error (C++ function) 13259 @anchor{cp/topics/contexts _CPPv4N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{1bb}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{1bc}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{1bd}@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{1be} 13260 @deffn {C++ Function} const char *gccjit::@ref{175,,context}::get_first_error (gccjit::context *ctxt) 13261 13262 Returns the first error message that occurred on the context. 13263 13264 The returned string is valid for the rest of the lifetime of the 13265 context. 13266 13267 If no errors occurred, this will be NULL. 13268 @end deffn 13269 13270 @node Debugging<2>,Options<4>,Error-handling<3>,Compilation contexts<2> 13271 @anchor{cp/topics/contexts debugging}@anchor{1bf} 13272 @subsubsection Debugging 13273 13274 13275 @geindex gccjit;;context;;dump_to_file (C++ function) 13276 @anchor{cp/topics/contexts _CPPv4N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{1c0}@anchor{cp/topics/contexts _CPPv3N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{1c1}@anchor{cp/topics/contexts _CPPv2N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{1c2}@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{1c3} 13277 @deffn {C++ Function} void gccjit::@ref{175,,context}::dump_to_file (const std::string &path, int update_locations) 13278 13279 To help with debugging: dump a C-like representation to the given path, 13280 describing whats been set up on the context. 13281 13282 If update_locations is true, then also set up @ref{19b,,gccjit;;location} 13283 information throughout the context, pointing at the dump file as if it 13284 were a source file. This may be of use in conjunction with 13285 @code{GCCJIT::BOOL_OPTION_DEBUGINFO} to allow stepping through the 13286 code in a debugger. 13287 @end deffn 13288 13289 @geindex gccjit;;context;;dump_reproducer_to_file (C++ function) 13290 @anchor{cp/topics/contexts _CPPv4N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{1c4}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{1c5}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{1c6}@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{1c7} 13291 @deffn {C++ Function} void gccjit::@ref{175,,context}::dump_reproducer_to_file (gcc_jit_context *ctxt, const char *path) 13292 13293 This is a thin wrapper around the C API 13294 @ref{5d,,gcc_jit_context_dump_reproducer_to_file()}, and hence works the 13295 same way. 13296 13297 Note that the generated source is C code, not C++; this might be of use 13298 for seeing what the C++ bindings are doing at the C level. 13299 @end deffn 13300 13301 @node Options<4>,,Debugging<2>,Compilation contexts<2> 13302 @anchor{cp/topics/contexts options}@anchor{1c8} 13303 @subsubsection Options 13304 13305 13306 @menu 13307 * String Options: String Options<2>. 13308 * Boolean options: Boolean options<2>. 13309 * Integer options: Integer options<2>. 13310 * Additional command-line options: Additional command-line options<2>. 13311 13312 @end menu 13313 13314 @node String Options<2>,Boolean options<2>,,Options<4> 13315 @anchor{cp/topics/contexts string-options}@anchor{1c9} 13316 @subsubsection String Options 13317 13318 13319 @geindex gccjit;;context;;set_str_option (C++ function) 13320 @anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{1ca}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{1cb}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{1cc}@anchor{cp/topics/contexts gccjit context set_str_option__gcc_jit_str_option cCP}@anchor{1cd} 13321 @deffn {C++ Function} void gccjit::@ref{175,,context}::set_str_option (enum gcc_jit_str_option, const char *value) 13322 13323 Set a string option of the context. 13324 13325 This is a thin wrapper around the C API 13326 @ref{61,,gcc_jit_context_set_str_option()}; the options have the same 13327 meaning. 13328 @end deffn 13329 13330 @node Boolean options<2>,Integer options<2>,String Options<2>,Options<4> 13331 @anchor{cp/topics/contexts boolean-options}@anchor{1ce} 13332 @subsubsection Boolean options 13333 13334 13335 @geindex gccjit;;context;;set_bool_option (C++ function) 13336 @anchor{cp/topics/contexts _CPPv4N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{181}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{1cf}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{1d0}@anchor{cp/topics/contexts gccjit context set_bool_option__gcc_jit_bool_option i}@anchor{1d1} 13337 @deffn {C++ Function} void gccjit::@ref{175,,context}::set_bool_option (enum gcc_jit_bool_option, int value) 13338 13339 Set a boolean option of the context. 13340 13341 This is a thin wrapper around the C API 13342 @ref{1b,,gcc_jit_context_set_bool_option()}; the options have the same 13343 meaning. 13344 @end deffn 13345 13346 @geindex gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function) 13347 @anchor{cp/topics/contexts _CPPv4N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{1d2}@anchor{cp/topics/contexts _CPPv3N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{1d3}@anchor{cp/topics/contexts _CPPv2N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{1d4}@anchor{cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i}@anchor{1d5} 13348 @deffn {C++ Function} void gccjit::@ref{175,,context}::set_bool_allow_unreachable_blocks (int bool_value) 13349 13350 By default, libgccjit will issue an error about unreachable blocks 13351 within a function. 13352 13353 This entrypoint can be used to disable that error; it is a thin wrapper 13354 around the C API 13355 @ref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()}. 13356 13357 This entrypoint was added in @ref{6c,,LIBGCCJIT_ABI_2}; you can test for 13358 its presence using 13359 13360 @example 13361 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks 13362 @end example 13363 @end deffn 13364 13365 @geindex gccjit;;context;;set_bool_use_external_driver (C++ function) 13366 @anchor{cp/topics/contexts _CPPv4N6gccjit7context28set_bool_use_external_driverEi}@anchor{1d6}@anchor{cp/topics/contexts _CPPv3N6gccjit7context28set_bool_use_external_driverEi}@anchor{1d7}@anchor{cp/topics/contexts _CPPv2N6gccjit7context28set_bool_use_external_driverEi}@anchor{1d8}@anchor{cp/topics/contexts gccjit context set_bool_use_external_driver__i}@anchor{1d9} 13367 @deffn {C++ Function} void gccjit::@ref{175,,context}::set_bool_use_external_driver (int bool_value) 13368 13369 libgccjit internally generates assembler, and uses driver code 13370 for converting it to other formats (e.g. shared libraries). 13371 13372 By default, libgccjit will use an embedded copy of the driver 13373 code. 13374 13375 This option can be used to instead invoke an external driver executable 13376 as a subprocess; it is a thin wrapper around the C API 13377 @ref{6d,,gcc_jit_context_set_bool_use_external_driver()}. 13378 13379 This entrypoint was added in @ref{6e,,LIBGCCJIT_ABI_5}; you can test for 13380 its presence using 13381 13382 @example 13383 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver 13384 @end example 13385 @end deffn 13386 13387 @node Integer options<2>,Additional command-line options<2>,Boolean options<2>,Options<4> 13388 @anchor{cp/topics/contexts integer-options}@anchor{1da} 13389 @subsubsection Integer options 13390 13391 13392 @geindex gccjit;;context;;set_int_option (C++ function) 13393 @anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{182}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1db}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1dc}@anchor{cp/topics/contexts gccjit context set_int_option__gcc_jit_int_option i}@anchor{1dd} 13394 @deffn {C++ Function} void gccjit::@ref{175,,context}::set_int_option (enum gcc_jit_int_option, int value) 13395 13396 Set an integer option of the context. 13397 13398 This is a thin wrapper around the C API 13399 @ref{1e,,gcc_jit_context_set_int_option()}; the options have the same 13400 meaning. 13401 @end deffn 13402 13403 @node Additional command-line options<2>,,Integer options<2>,Options<4> 13404 @anchor{cp/topics/contexts additional-command-line-options}@anchor{1de} 13405 @subsubsection Additional command-line options 13406 13407 13408 @geindex gccjit;;context;;add_command_line_option (C++ function) 13409 @anchor{cp/topics/contexts _CPPv4N6gccjit7context23add_command_line_optionEPKc}@anchor{1df}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23add_command_line_optionEPKc}@anchor{1e0}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23add_command_line_optionEPKc}@anchor{1e1}@anchor{cp/topics/contexts gccjit context add_command_line_option__cCP}@anchor{1e2} 13410 @deffn {C++ Function} void gccjit::@ref{175,,context}::add_command_line_option (const char *optname) 13411 13412 Add an arbitrary gcc command-line option to the context for use 13413 when compiling. 13414 13415 This is a thin wrapper around the C API 13416 @ref{74,,gcc_jit_context_add_command_line_option()}. 13417 13418 This entrypoint was added in @ref{75,,LIBGCCJIT_ABI_1}; you can test for 13419 its presence using 13420 13421 @example 13422 #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option 13423 @end example 13424 @end deffn 13425 13426 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 13427 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 13428 @c 13429 @c This is free software: you can redistribute it and/or modify it 13430 @c under the terms of the GNU General Public License as published by 13431 @c the Free Software Foundation, either version 3 of the License, or 13432 @c (at your option) any later version. 13433 @c 13434 @c This program is distributed in the hope that it will be useful, but 13435 @c WITHOUT ANY WARRANTY; without even the implied warranty of 13436 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13437 @c General Public License for more details. 13438 @c 13439 @c You should have received a copy of the GNU General Public License 13440 @c along with this program. If not, see 13441 @c <https://www.gnu.org/licenses/>. 13442 13443 @node Objects<2>,Types<2>,Compilation contexts<2>,Topic Reference<2> 13444 @anchor{cp/topics/objects doc}@anchor{1e3}@anchor{cp/topics/objects objects}@anchor{1e4} 13445 @subsection Objects 13446 13447 13448 @geindex gccjit;;object (C++ class) 13449 @anchor{cp/topics/objects _CPPv4N6gccjit6objectE}@anchor{17a}@anchor{cp/topics/objects _CPPv3N6gccjit6objectE}@anchor{1e5}@anchor{cp/topics/objects _CPPv2N6gccjit6objectE}@anchor{1e6}@anchor{cp/topics/objects gccjit object}@anchor{1e7} 13450 @deffn {C++ Class} gccjit::object 13451 @end deffn 13452 13453 Almost every entity in the API (with the exception of 13454 @ref{175,,gccjit;;context} and @ref{16,,gcc_jit_result *}) is a 13455 contextual object, a @ref{17a,,gccjit;;object}. 13456 13457 A JIT object: 13458 13459 @quotation 13460 13461 13462 @itemize * 13463 13464 @item 13465 is associated with a @ref{175,,gccjit;;context}. 13466 13467 @item 13468 is automatically cleaned up for you when its context is released so 13469 you dont need to manually track and cleanup all objects, just the 13470 contexts. 13471 @end itemize 13472 @end quotation 13473 13474 The C++ class hierarchy within the @code{gccjit} namespace looks like this: 13475 13476 @example 13477 +- object 13478 +- location 13479 +- type 13480 +- struct 13481 +- field 13482 +- function 13483 +- block 13484 +- rvalue 13485 +- lvalue 13486 +- param 13487 +- case_ 13488 @end example 13489 13490 The @ref{17a,,gccjit;;object} base class has the following operations: 13491 13492 @geindex gccjit;;object;;get_context (C++ function) 13493 @anchor{cp/topics/objects _CPPv4NK6gccjit6object11get_contextEv}@anchor{1e8}@anchor{cp/topics/objects _CPPv3NK6gccjit6object11get_contextEv}@anchor{1e9}@anchor{cp/topics/objects _CPPv2NK6gccjit6object11get_contextEv}@anchor{1ea}@anchor{cp/topics/objects gccjit object get_contextC}@anchor{1eb} 13494 @deffn {C++ Function} gccjit::@ref{175,,context} gccjit::@ref{17a,,object}::get_context () const 13495 13496 Which context is the obj within? 13497 @end deffn 13498 13499 @geindex gccjit;;object;;get_debug_string (C++ function) 13500 @anchor{cp/topics/objects _CPPv4NK6gccjit6object16get_debug_stringEv}@anchor{17b}@anchor{cp/topics/objects _CPPv3NK6gccjit6object16get_debug_stringEv}@anchor{1ec}@anchor{cp/topics/objects _CPPv2NK6gccjit6object16get_debug_stringEv}@anchor{1ed}@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{1ee} 13501 @deffn {C++ Function} std::string gccjit::@ref{17a,,object}::get_debug_string () const 13502 13503 Generate a human-readable description for the given object. 13504 13505 For example, 13506 13507 @example 13508 printf ("obj: %s\n", obj.get_debug_string ().c_str ()); 13509 @end example 13510 13511 might give this text on stdout: 13512 13513 @example 13514 obj: 4.0 * (float)i 13515 @end example 13516 @end deffn 13517 13518 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 13519 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 13520 @c 13521 @c This is free software: you can redistribute it and/or modify it 13522 @c under the terms of the GNU General Public License as published by 13523 @c the Free Software Foundation, either version 3 of the License, or 13524 @c (at your option) any later version. 13525 @c 13526 @c This program is distributed in the hope that it will be useful, but 13527 @c WITHOUT ANY WARRANTY; without even the implied warranty of 13528 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13529 @c General Public License for more details. 13530 @c 13531 @c You should have received a copy of the GNU General Public License 13532 @c along with this program. If not, see 13533 @c <https://www.gnu.org/licenses/>. 13534 13535 @node Types<2>,Expressions<2>,Objects<2>,Topic Reference<2> 13536 @anchor{cp/topics/types doc}@anchor{1ef}@anchor{cp/topics/types types}@anchor{1f0} 13537 @subsection Types 13538 13539 13540 @geindex gccjit;;type (C++ class) 13541 @anchor{cp/topics/types _CPPv4N6gccjit4typeE}@anchor{177}@anchor{cp/topics/types _CPPv3N6gccjit4typeE}@anchor{1f1}@anchor{cp/topics/types _CPPv2N6gccjit4typeE}@anchor{1f2}@anchor{cp/topics/types gccjit type}@anchor{1f3} 13542 @deffn {C++ Class} gccjit::type 13543 13544 gccjit::type represents a type within the library. It is a subclass 13545 of @ref{17a,,gccjit;;object}. 13546 @end deffn 13547 13548 Types can be created in several ways: 13549 13550 13551 @itemize * 13552 13553 @item 13554 fundamental types can be accessed using 13555 @ref{178,,gccjit;;context;;get_type()}: 13556 13557 @example 13558 gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 13559 @end example 13560 13561 or using the @code{gccjit::context::get_int_type} template: 13562 13563 @example 13564 gccjit::type t = ctxt.get_int_type <unsigned short> (); 13565 @end example 13566 13567 See @ref{b,,gcc_jit_context_get_type()} for the available types. 13568 13569 @item 13570 derived types can be accessed by using functions such as 13571 @ref{1f4,,gccjit;;type;;get_pointer()} and @ref{1f5,,gccjit;;type;;get_const()}: 13572 13573 @example 13574 gccjit::type const_int_star = int_type.get_const ().get_pointer (); 13575 gccjit::type int_const_star = int_type.get_pointer ().get_const (); 13576 @end example 13577 13578 @item 13579 by creating structures (see below). 13580 @end itemize 13581 13582 @menu 13583 * Standard types: Standard types<2>. 13584 * Pointers@comma{} const@comma{} and volatile: Pointers const and volatile<2>. 13585 * Vector types: Vector types<2>. 13586 * Structures and unions: Structures and unions<2>. 13587 13588 @end menu 13589 13590 @node Standard types<2>,Pointers const and volatile<2>,,Types<2> 13591 @anchor{cp/topics/types standard-types}@anchor{1f6} 13592 @subsubsection Standard types 13593 13594 13595 @geindex gccjit;;context;;get_type (C++ function) 13596 @anchor{cp/topics/types _CPPv4N6gccjit7context8get_typeE13gcc_jit_types}@anchor{178}@anchor{cp/topics/types _CPPv3N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1f7}@anchor{cp/topics/types _CPPv2N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1f8}@anchor{cp/topics/types gccjit context get_type__gcc_jit_types}@anchor{1f9} 13597 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{175,,context}::get_type (enum gcc_jit_types) 13598 13599 Access a specific type. This is a thin wrapper around 13600 @ref{b,,gcc_jit_context_get_type()}; the parameter has the same meaning. 13601 @end deffn 13602 13603 @geindex gccjit;;context;;get_int_type (C++ function) 13604 @anchor{cp/topics/types _CPPv4N6gccjit7context12get_int_typeE6size_ti}@anchor{1fa}@anchor{cp/topics/types _CPPv3N6gccjit7context12get_int_typeE6size_ti}@anchor{1fb}@anchor{cp/topics/types _CPPv2N6gccjit7context12get_int_typeE6size_ti}@anchor{1fc}@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{1fd} 13605 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{175,,context}::get_int_type (size_t num_bytes, int is_signed) 13606 13607 Access the integer type of the given size. 13608 @end deffn 13609 13610 @geindex gccjit;;context;;get_int_type<T> (C++ function) 13611 @anchor{cp/topics/types _CPPv4IEN6gccjit7context12get_int_typeI1TEEN6gccjit4typeEv}@anchor{1fe}@anchor{cp/topics/types _CPPv3IEN6gccjit7context12get_int_typeI1TEEv}@anchor{1ff}@anchor{cp/topics/types _CPPv2IEN6gccjit7context12get_int_typeI1TEEv}@anchor{200} 13612 @deffn {C++ Function} template<>gccjit::@ref{177,,type} gccjit::@ref{175,,context}::get_int_type<T> () 13613 13614 Access the given integer type. For example, you could map the 13615 @code{unsigned short} type into a gccjit::type via: 13616 13617 @example 13618 gccjit::type t = ctxt.get_int_type <unsigned short> (); 13619 @end example 13620 @end deffn 13621 13622 @node Pointers const and volatile<2>,Vector types<2>,Standard types<2>,Types<2> 13623 @anchor{cp/topics/types pointers-const-and-volatile}@anchor{201} 13624 @subsubsection Pointers, @cite{const}, and @cite{volatile} 13625 13626 13627 @geindex gccjit;;type;;get_pointer (C++ function) 13628 @anchor{cp/topics/types _CPPv4N6gccjit4type11get_pointerEv}@anchor{1f4}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_pointerEv}@anchor{202}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_pointerEv}@anchor{203}@anchor{cp/topics/types gccjit type get_pointer}@anchor{204} 13629 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{177,,type}::get_pointer () 13630 13631 Given type T, get type T*. 13632 @end deffn 13633 13634 @geindex gccjit;;type;;get_const (C++ function) 13635 @anchor{cp/topics/types _CPPv4N6gccjit4type9get_constEv}@anchor{1f5}@anchor{cp/topics/types _CPPv3N6gccjit4type9get_constEv}@anchor{205}@anchor{cp/topics/types _CPPv2N6gccjit4type9get_constEv}@anchor{206}@anchor{cp/topics/types gccjit type get_const}@anchor{207} 13636 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{177,,type}::get_const () 13637 13638 Given type T, get type const T. 13639 @end deffn 13640 13641 @geindex gccjit;;type;;get_volatile (C++ function) 13642 @anchor{cp/topics/types _CPPv4N6gccjit4type12get_volatileEv}@anchor{208}@anchor{cp/topics/types _CPPv3N6gccjit4type12get_volatileEv}@anchor{209}@anchor{cp/topics/types _CPPv2N6gccjit4type12get_volatileEv}@anchor{20a}@anchor{cp/topics/types gccjit type get_volatile}@anchor{20b} 13643 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{177,,type}::get_volatile () 13644 13645 Given type T, get type volatile T. 13646 @end deffn 13647 13648 @geindex gccjit;;type;;get_aligned (C++ function) 13649 @anchor{cp/topics/types _CPPv4N6gccjit4type11get_alignedE6size_t}@anchor{20c}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_alignedE6size_t}@anchor{20d}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_alignedE6size_t}@anchor{20e}@anchor{cp/topics/types gccjit type get_aligned__s}@anchor{20f} 13650 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{177,,type}::get_aligned (size_t alignment_in_bytes) 13651 13652 Given type T, get type: 13653 13654 @example 13655 T __attribute__ ((aligned (ALIGNMENT_IN_BYTES))) 13656 @end example 13657 13658 The alignment must be a power of two. 13659 @end deffn 13660 13661 @geindex gccjit;;context;;new_array_type (C++ function) 13662 @anchor{cp/topics/types _CPPv4N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{210}@anchor{cp/topics/types _CPPv3N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{211}@anchor{cp/topics/types _CPPv2N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{212}@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{213} 13663 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{175,,context}::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc) 13664 13665 Given type T, get type T[N] (for a constant N). 13666 Param loc is optional. 13667 @end deffn 13668 13669 @node Vector types<2>,Structures and unions<2>,Pointers const and volatile<2>,Types<2> 13670 @anchor{cp/topics/types vector-types}@anchor{214} 13671 @subsubsection Vector types 13672 13673 13674 @geindex gccjit;;type;;get_vector (C++ function) 13675 @anchor{cp/topics/types _CPPv4N6gccjit4type10get_vectorE6size_t}@anchor{215}@anchor{cp/topics/types _CPPv3N6gccjit4type10get_vectorE6size_t}@anchor{216}@anchor{cp/topics/types _CPPv2N6gccjit4type10get_vectorE6size_t}@anchor{217}@anchor{cp/topics/types gccjit type get_vector__s}@anchor{218} 13676 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{177,,type}::get_vector (size_t num_units) 13677 13678 Given type T, get type: 13679 13680 @example 13681 T __attribute__ ((vector_size (sizeof(T) * num_units)) 13682 @end example 13683 13684 T must be integral or floating point; num_units must be a power of two. 13685 @end deffn 13686 13687 @node Structures and unions<2>,,Vector types<2>,Types<2> 13688 @anchor{cp/topics/types structures-and-unions}@anchor{219} 13689 @subsubsection Structures and unions 13690 13691 13692 @geindex gccjit;;struct_ (C++ class) 13693 @anchor{cp/topics/types _CPPv4N6gccjit7struct_E}@anchor{21a}@anchor{cp/topics/types _CPPv3N6gccjit7struct_E}@anchor{21b}@anchor{cp/topics/types _CPPv2N6gccjit7struct_E}@anchor{21c}@anchor{cp/topics/types gccjit struct_}@anchor{21d} 13694 @deffn {C++ Class} gccjit::struct_ 13695 @end deffn 13696 13697 A compound type analagous to a C @cite{struct}. 13698 13699 @ref{21a,,gccjit;;struct_} is a subclass of @ref{177,,gccjit;;type} (and thus 13700 of @ref{17a,,gccjit;;object} in turn). 13701 13702 @geindex gccjit;;field (C++ class) 13703 @anchor{cp/topics/types _CPPv4N6gccjit5fieldE}@anchor{21e}@anchor{cp/topics/types _CPPv3N6gccjit5fieldE}@anchor{21f}@anchor{cp/topics/types _CPPv2N6gccjit5fieldE}@anchor{220}@anchor{cp/topics/types gccjit field}@anchor{221} 13704 @deffn {C++ Class} gccjit::field 13705 @end deffn 13706 13707 A field within a @ref{21a,,gccjit;;struct_}. 13708 13709 @ref{21e,,gccjit;;field} is a subclass of @ref{17a,,gccjit;;object}. 13710 13711 You can model C @cite{struct} types by creating @ref{21a,,gccjit;;struct_} and 13712 @ref{21e,,gccjit;;field} instances, in either order: 13713 13714 13715 @itemize * 13716 13717 @item 13718 by creating the fields, then the structure. For example, to model: 13719 13720 @example 13721 struct coord @{double x; double y; @}; 13722 @end example 13723 13724 you could call: 13725 13726 @example 13727 gccjit::field field_x = ctxt.new_field (double_type, "x"); 13728 gccjit::field field_y = ctxt.new_field (double_type, "y"); 13729 std::vector fields; 13730 fields.push_back (field_x); 13731 fields.push_back (field_y); 13732 gccjit::struct_ coord = ctxt.new_struct_type ("coord", fields); 13733 @end example 13734 13735 @item 13736 by creating the structure, then populating it with fields, typically 13737 to allow modelling self-referential structs such as: 13738 13739 @example 13740 struct node @{ int m_hash; struct node *m_next; @}; 13741 @end example 13742 13743 like this: 13744 13745 @example 13746 gccjit::struct_ node = ctxt.new_opaque_struct_type ("node"); 13747 gccjit::type node_ptr = node.get_pointer (); 13748 gccjit::field field_hash = ctxt.new_field (int_type, "m_hash"); 13749 gccjit::field field_next = ctxt.new_field (node_ptr, "m_next"); 13750 std::vector fields; 13751 fields.push_back (field_hash); 13752 fields.push_back (field_next); 13753 node.set_fields (fields); 13754 @end example 13755 @end itemize 13756 13757 @c FIXME: the above API doesn't seem to exist yet 13758 13759 @geindex gccjit;;context;;new_field (C++ function) 13760 @anchor{cp/topics/types _CPPv4N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{222}@anchor{cp/topics/types _CPPv3N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{223}@anchor{cp/topics/types _CPPv2N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{224}@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{225} 13761 @deffn {C++ Function} gccjit::@ref{21e,,field} gccjit::@ref{175,,context}::new_field (gccjit::type type, const char *name, gccjit::location loc) 13762 13763 Construct a new field, with the given type and name. 13764 @end deffn 13765 13766 @geindex gccjit;;context;;new_struct_type (C++ function) 13767 @anchor{cp/topics/types _CPPv4N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{226}@anchor{cp/topics/types _CPPv3N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{227}@anchor{cp/topics/types _CPPv2N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{228}@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{229} 13768 @deffn {C++ Function} gccjit::@ref{21a,,struct_} gccjit::@ref{175,,context}::new_struct_type (const std::string &name, std::vector<field> &fields, gccjit::location loc) 13769 13770 @quotation 13771 13772 Construct a new struct type, with the given name and fields. 13773 @end quotation 13774 @end deffn 13775 13776 @geindex gccjit;;context;;new_opaque_struct (C++ function) 13777 @anchor{cp/topics/types _CPPv4N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{22a}@anchor{cp/topics/types _CPPv3N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{22b}@anchor{cp/topics/types _CPPv2N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{22c}@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{22d} 13778 @deffn {C++ Function} gccjit::@ref{21a,,struct_} gccjit::@ref{175,,context}::new_opaque_struct (const std::string &name, gccjit::location loc) 13779 13780 Construct a new struct type, with the given name, but without 13781 specifying the fields. The fields can be omitted (in which case the 13782 size of the struct is not known), or later specified using 13783 @ref{93,,gcc_jit_struct_set_fields()}. 13784 @end deffn 13785 13786 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 13787 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 13788 @c 13789 @c This is free software: you can redistribute it and/or modify it 13790 @c under the terms of the GNU General Public License as published by 13791 @c the Free Software Foundation, either version 3 of the License, or 13792 @c (at your option) any later version. 13793 @c 13794 @c This program is distributed in the hope that it will be useful, but 13795 @c WITHOUT ANY WARRANTY; without even the implied warranty of 13796 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13797 @c General Public License for more details. 13798 @c 13799 @c You should have received a copy of the GNU General Public License 13800 @c along with this program. If not, see 13801 @c <https://www.gnu.org/licenses/>. 13802 13803 @node Expressions<2>,Creating and using functions<2>,Types<2>,Topic Reference<2> 13804 @anchor{cp/topics/expressions doc}@anchor{22e}@anchor{cp/topics/expressions expressions}@anchor{22f} 13805 @subsection Expressions 13806 13807 13808 @menu 13809 * Rvalues: Rvalues<2>. 13810 * Lvalues: Lvalues<2>. 13811 * Working with pointers@comma{} structs and unions: Working with pointers structs and unions<2>. 13812 13813 @end menu 13814 13815 @node Rvalues<2>,Lvalues<2>,,Expressions<2> 13816 @anchor{cp/topics/expressions rvalues}@anchor{230} 13817 @subsubsection Rvalues 13818 13819 13820 @geindex gccjit;;rvalue (C++ class) 13821 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvalueE}@anchor{17e}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalueE}@anchor{231}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalueE}@anchor{232}@anchor{cp/topics/expressions gccjit rvalue}@anchor{233} 13822 @deffn {C++ Class} gccjit::rvalue 13823 @end deffn 13824 13825 A @ref{17e,,gccjit;;rvalue} is an expression that can be computed. It is a 13826 subclass of @ref{17a,,gccjit;;object}, and is a thin wrapper around 13827 @ref{13,,gcc_jit_rvalue *} from the C API. 13828 13829 It can be simple, e.g.: 13830 13831 @quotation 13832 13833 13834 @itemize * 13835 13836 @item 13837 an integer value e.g. @cite{0} or @cite{42} 13838 13839 @item 13840 a string literal e.g. @cite{Hello world} 13841 13842 @item 13843 a variable e.g. @cite{i}. These are also lvalues (see below). 13844 @end itemize 13845 @end quotation 13846 13847 or compound e.g.: 13848 13849 @quotation 13850 13851 13852 @itemize * 13853 13854 @item 13855 a unary expression e.g. @cite{!cond} 13856 13857 @item 13858 a binary expression e.g. @cite{(a + b)} 13859 13860 @item 13861 a function call e.g. @cite{get_distance (&player_ship@comma{} &target)} 13862 13863 @item 13864 etc. 13865 @end itemize 13866 @end quotation 13867 13868 Every rvalue has an associated type, and the API will check to ensure 13869 that types match up correctly (otherwise the context will emit an error). 13870 13871 @geindex gccjit;;rvalue;;get_type (C++ function) 13872 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue8get_typeEv}@anchor{234}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue8get_typeEv}@anchor{235}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue8get_typeEv}@anchor{236}@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{237} 13873 @deffn {C++ Function} gccjit::@ref{177,,type} gccjit::@ref{17e,,rvalue}::get_type () 13874 13875 Get the type of this rvalue. 13876 @end deffn 13877 13878 @menu 13879 * Simple expressions: Simple expressions<2>. 13880 * Vector expressions: Vector expressions<2>. 13881 * Unary Operations: Unary Operations<2>. 13882 * Binary Operations: Binary Operations<2>. 13883 * Comparisons: Comparisons<2>. 13884 * Function calls: Function calls<2>. 13885 * Function pointers: Function pointers<3>. 13886 * Type-coercion: Type-coercion<2>. 13887 13888 @end menu 13889 13890 @node Simple expressions<2>,Vector expressions<2>,,Rvalues<2> 13891 @anchor{cp/topics/expressions simple-expressions}@anchor{238} 13892 @subsubsection Simple expressions 13893 13894 13895 @geindex gccjit;;context;;new_rvalue (C++ function) 13896 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{192}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{239}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{23a}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{23b} 13897 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (gccjit::type numeric_type, int value) const 13898 13899 Given a numeric type (integer or floating point), build an rvalue for 13900 the given constant @code{int} value. 13901 @end deffn 13902 13903 @geindex gccjit;;context;;new_rvalue (C++ function) 13904 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{23c}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{23d}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{23e}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{23f} 13905 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (gccjit::type numeric_type, long value) const 13906 13907 Given a numeric type (integer or floating point), build an rvalue for 13908 the given constant @code{long} value. 13909 @end deffn 13910 13911 @geindex gccjit;;context;;zero (C++ function) 13912 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{18e}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{240}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{241}@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{242} 13913 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::zero (gccjit::type numeric_type) const 13914 13915 Given a numeric type (integer or floating point), get the rvalue for 13916 zero. Essentially this is just a shortcut for: 13917 13918 @example 13919 ctxt.new_rvalue (numeric_type, 0) 13920 @end example 13921 @end deffn 13922 13923 @geindex gccjit;;context;;one (C++ function) 13924 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context3oneEN6gccjit4typeE}@anchor{243}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context3oneEN6gccjit4typeE}@anchor{244}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context3oneEN6gccjit4typeE}@anchor{245}@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{246} 13925 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::one (gccjit::type numeric_type) const 13926 13927 Given a numeric type (integer or floating point), get the rvalue for 13928 one. Essentially this is just a shortcut for: 13929 13930 @example 13931 ctxt.new_rvalue (numeric_type, 1) 13932 @end example 13933 @end deffn 13934 13935 @geindex gccjit;;context;;new_rvalue (C++ function) 13936 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{247}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{248}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{249}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{24a} 13937 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (gccjit::type numeric_type, double value) const 13938 13939 Given a numeric type (integer or floating point), build an rvalue for 13940 the given constant @code{double} value. 13941 @end deffn 13942 13943 @geindex gccjit;;context;;new_rvalue (C++ function) 13944 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{24b}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{24c}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{24d}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{24e} 13945 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (gccjit::type pointer_type, void *value) const 13946 13947 Given a pointer type, build an rvalue for the given address. 13948 @end deffn 13949 13950 @geindex gccjit;;context;;new_rvalue (C++ function) 13951 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{24f}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{250}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{251}@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{252} 13952 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (const std::string &value) const 13953 13954 Generate an rvalue of type @code{GCC_JIT_TYPE_CONST_CHAR_PTR} for 13955 the given string. This is akin to a string literal. 13956 @end deffn 13957 13958 @node Vector expressions<2>,Unary Operations<2>,Simple expressions<2>,Rvalues<2> 13959 @anchor{cp/topics/expressions vector-expressions}@anchor{253} 13960 @subsubsection Vector expressions 13961 13962 13963 @geindex gccjit;;context;;new_rvalue (C++ function) 13964 @anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{254}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{255}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{256}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C}@anchor{257} 13965 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_rvalue (gccjit::type vector_type, std::vector<gccjit::rvalue> elements) const 13966 13967 Given a vector type, and a vector of scalar rvalue elements, generate a 13968 vector rvalue. 13969 13970 The number of elements needs to match that of the vector type. 13971 @end deffn 13972 13973 @node Unary Operations<2>,Binary Operations<2>,Vector expressions<2>,Rvalues<2> 13974 @anchor{cp/topics/expressions unary-operations}@anchor{258} 13975 @subsubsection Unary Operations 13976 13977 13978 @geindex gccjit;;context;;new_unary_op (C++ function) 13979 @anchor{cp/topics/expressions _CPPv4N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{259}@anchor{cp/topics/expressions _CPPv3N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25b}@anchor{cp/topics/expressions gccjit context new_unary_op__gcc_jit_unary_op gccjit type gccjit rvalue gccjit location}@anchor{25c} 13980 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc) 13981 13982 Build a unary operation out of an input rvalue. 13983 13984 Parameter @code{loc} is optional. 13985 13986 This is a thin wrapper around the C APIs 13987 @ref{bf,,gcc_jit_context_new_unary_op()} and the available unary 13988 operations are documented there. 13989 @end deffn 13990 13991 There are shorter ways to spell the various specific kinds of unary 13992 operation: 13993 13994 @geindex gccjit;;context;;new_minus (C++ function) 13995 @anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25f}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{260} 13996 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 13997 13998 Negate an arithmetic value; for example: 13999 14000 @example 14001 gccjit::rvalue negpi = ctxt.new_minus (t_double, pi); 14002 @end example 14003 14004 builds the equivalent of this C expression: 14005 14006 @example 14007 -pi 14008 @end example 14009 @end deffn 14010 14011 @geindex new_bitwise_negate (C++ function) 14012 @anchor{cp/topics/expressions _CPPv418new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{261}@anchor{cp/topics/expressions _CPPv318new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{262}@anchor{cp/topics/expressions _CPPv218new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{263}@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{264} 14013 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 14014 14015 Bitwise negation of an integer value (ones complement); for example: 14016 14017 @example 14018 gccjit::rvalue mask = ctxt.new_bitwise_negate (t_int, a); 14019 @end example 14020 14021 builds the equivalent of this C expression: 14022 14023 @example 14024 ~a 14025 @end example 14026 @end deffn 14027 14028 @geindex new_logical_negate (C++ function) 14029 @anchor{cp/topics/expressions _CPPv418new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{265}@anchor{cp/topics/expressions _CPPv318new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{266}@anchor{cp/topics/expressions _CPPv218new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{267}@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{268} 14030 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 14031 14032 Logical negation of an arithmetic or pointer value; for example: 14033 14034 @example 14035 gccjit::rvalue guard = ctxt.new_logical_negate (t_bool, cond); 14036 @end example 14037 14038 builds the equivalent of this C expression: 14039 14040 @example 14041 !cond 14042 @end example 14043 @end deffn 14044 14045 The most concise way to spell them is with overloaded operators: 14046 14047 @geindex operator- (C++ function) 14048 @anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueE}@anchor{269}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueE}@anchor{26a}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueE}@anchor{26b}@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{26c} 14049 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator@w{-} (gccjit::rvalue a) 14050 14051 @example 14052 gccjit::rvalue negpi = -pi; 14053 @end example 14054 @end deffn 14055 14056 @geindex operator~ (C++ function) 14057 @anchor{cp/topics/expressions _CPPv4coN6gccjit6rvalueE}@anchor{26d}@anchor{cp/topics/expressions _CPPv3coN6gccjit6rvalueE}@anchor{26e}@anchor{cp/topics/expressions _CPPv2coN6gccjit6rvalueE}@anchor{26f}@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{270} 14058 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator~ (gccjit::rvalue a) 14059 14060 @example 14061 gccjit::rvalue mask = ~a; 14062 @end example 14063 @end deffn 14064 14065 @geindex operator! (C++ function) 14066 @anchor{cp/topics/expressions _CPPv4ntN6gccjit6rvalueE}@anchor{271}@anchor{cp/topics/expressions _CPPv3ntN6gccjit6rvalueE}@anchor{272}@anchor{cp/topics/expressions _CPPv2ntN6gccjit6rvalueE}@anchor{273}@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{274} 14067 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator! (gccjit::rvalue a) 14068 14069 @example 14070 gccjit::rvalue guard = !cond; 14071 @end example 14072 @end deffn 14073 14074 @node Binary Operations<2>,Comparisons<2>,Unary Operations<2>,Rvalues<2> 14075 @anchor{cp/topics/expressions binary-operations}@anchor{275} 14076 @subsubsection Binary Operations 14077 14078 14079 @geindex gccjit;;context;;new_binary_op (C++ function) 14080 @anchor{cp/topics/expressions _CPPv4N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{17d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{276}@anchor{cp/topics/expressions _CPPv2N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{277}@anchor{cp/topics/expressions gccjit context new_binary_op__gcc_jit_binary_op gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{278} 14081 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14082 14083 Build a binary operation out of two constituent rvalues. 14084 14085 Parameter @code{loc} is optional. 14086 14087 This is a thin wrapper around the C APIs 14088 @ref{12,,gcc_jit_context_new_binary_op()} and the available binary 14089 operations are documented there. 14090 @end deffn 14091 14092 There are shorter ways to spell the various specific kinds of binary 14093 operation: 14094 14095 @geindex gccjit;;context;;new_plus (C++ function) 14096 @anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{279}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{27a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{27b}@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{27c} 14097 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14098 @end deffn 14099 14100 @geindex gccjit;;context;;new_minus (C++ function) 14101 @anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{27d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{27e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{27f}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{280} 14102 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14103 @end deffn 14104 14105 @geindex gccjit;;context;;new_mult (C++ function) 14106 @anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{281}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{282}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{283}@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{284} 14107 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14108 @end deffn 14109 14110 @geindex gccjit;;context;;new_divide (C++ function) 14111 @anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{285}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{286}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{287}@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{288} 14112 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14113 @end deffn 14114 14115 @geindex gccjit;;context;;new_modulo (C++ function) 14116 @anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{289}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{28a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{28b}@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{28c} 14117 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14118 @end deffn 14119 14120 @geindex gccjit;;context;;new_bitwise_and (C++ function) 14121 @anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{28d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{28e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{28f}@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{290} 14122 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14123 @end deffn 14124 14125 @geindex gccjit;;context;;new_bitwise_xor (C++ function) 14126 @anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{291}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{292}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{293}@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{294} 14127 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14128 @end deffn 14129 14130 @geindex gccjit;;context;;new_bitwise_or (C++ function) 14131 @anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{295}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{296}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{297}@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{298} 14132 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14133 @end deffn 14134 14135 @geindex gccjit;;context;;new_logical_and (C++ function) 14136 @anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{299}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29b}@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{29c} 14137 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14138 @end deffn 14139 14140 @geindex gccjit;;context;;new_logical_or (C++ function) 14141 @anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29f}@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{2a0} 14142 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14143 @end deffn 14144 14145 The most concise way to spell them is with overloaded operators: 14146 14147 @geindex operator+ (C++ function) 14148 @anchor{cp/topics/expressions _CPPv4plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a1}@anchor{cp/topics/expressions _CPPv3plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a2}@anchor{cp/topics/expressions _CPPv2plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a3}@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{2a4} 14149 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator+ (gccjit::rvalue a, gccjit::rvalue b) 14150 14151 @example 14152 gccjit::rvalue sum = a + b; 14153 @end example 14154 @end deffn 14155 14156 @geindex operator- (C++ function) 14157 @anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a5}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a6}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a7}@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{2a8} 14158 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator@w{-} (gccjit::rvalue a, gccjit::rvalue b) 14159 14160 @example 14161 gccjit::rvalue diff = a - b; 14162 @end example 14163 @end deffn 14164 14165 @geindex operator* (C++ function) 14166 @anchor{cp/topics/expressions _CPPv4mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2a9}@anchor{cp/topics/expressions _CPPv3mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2aa}@anchor{cp/topics/expressions _CPPv2mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ab}@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{2ac} 14167 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator* (gccjit::rvalue a, gccjit::rvalue b) 14168 14169 @example 14170 gccjit::rvalue prod = a * b; 14171 @end example 14172 @end deffn 14173 14174 @geindex operator/ (C++ function) 14175 @anchor{cp/topics/expressions _CPPv4dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ad}@anchor{cp/topics/expressions _CPPv3dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ae}@anchor{cp/topics/expressions _CPPv2dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2af}@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{2b0} 14176 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator/ (gccjit::rvalue a, gccjit::rvalue b) 14177 14178 @example 14179 gccjit::rvalue result = a / b; 14180 @end example 14181 @end deffn 14182 14183 @geindex operator% (C++ function) 14184 @anchor{cp/topics/expressions _CPPv4rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b1}@anchor{cp/topics/expressions _CPPv3rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b2}@anchor{cp/topics/expressions _CPPv2rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b3}@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{2b4} 14185 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator% (gccjit::rvalue a, gccjit::rvalue b) 14186 14187 @example 14188 gccjit::rvalue mod = a % b; 14189 @end example 14190 @end deffn 14191 14192 @geindex operator& (C++ function) 14193 @anchor{cp/topics/expressions _CPPv4anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b5}@anchor{cp/topics/expressions _CPPv3anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b6}@anchor{cp/topics/expressions _CPPv2anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b7}@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{2b8} 14194 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator& (gccjit::rvalue a, gccjit::rvalue b) 14195 14196 @example 14197 gccjit::rvalue x = a & b; 14198 @end example 14199 @end deffn 14200 14201 @geindex operator^ (C++ function) 14202 @anchor{cp/topics/expressions _CPPv4eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b9}@anchor{cp/topics/expressions _CPPv3eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ba}@anchor{cp/topics/expressions _CPPv2eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bb}@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{2bc} 14203 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator^ (gccjit::rvalue a, gccjit::rvalue b) 14204 14205 @example 14206 gccjit::rvalue x = a ^ b; 14207 @end example 14208 @end deffn 14209 14210 @geindex operator| (C++ function) 14211 @anchor{cp/topics/expressions _CPPv4orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bd}@anchor{cp/topics/expressions _CPPv3orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2be}@anchor{cp/topics/expressions _CPPv2orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bf}@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{2c0} 14212 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator| (gccjit::rvalue a, gccjit::rvalue b) 14213 14214 @example 14215 gccjit::rvalue x = a | b; 14216 @end example 14217 @end deffn 14218 14219 @geindex operator&& (C++ function) 14220 @anchor{cp/topics/expressions _CPPv4aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c1}@anchor{cp/topics/expressions _CPPv3aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c2}@anchor{cp/topics/expressions _CPPv2aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c3}@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{2c4} 14221 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator&& (gccjit::rvalue a, gccjit::rvalue b) 14222 14223 @example 14224 gccjit::rvalue cond = a && b; 14225 @end example 14226 @end deffn 14227 14228 @geindex operator|| (C++ function) 14229 @anchor{cp/topics/expressions _CPPv4ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c5}@anchor{cp/topics/expressions _CPPv3ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c6}@anchor{cp/topics/expressions _CPPv2ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c7}@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{2c8} 14230 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator|| (gccjit::rvalue a, gccjit::rvalue b) 14231 14232 @example 14233 gccjit::rvalue cond = a || b; 14234 @end example 14235 @end deffn 14236 14237 These can of course be combined, giving a terse way to build compound 14238 expressions: 14239 14240 @quotation 14241 14242 @example 14243 gccjit::rvalue discriminant = (b * b) - (four * a * c); 14244 @end example 14245 @end quotation 14246 14247 @node Comparisons<2>,Function calls<2>,Binary Operations<2>,Rvalues<2> 14248 @anchor{cp/topics/expressions comparisons}@anchor{2c9} 14249 @subsubsection Comparisons 14250 14251 14252 @geindex gccjit;;context;;new_comparison (C++ function) 14253 @anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{18f}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ca}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2cb}@anchor{cp/topics/expressions gccjit context new_comparison__gcc_jit_comparison gccjit rvalue gccjit rvalue gccjit location}@anchor{2cc} 14254 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14255 14256 Build a boolean rvalue out of the comparison of two other rvalues. 14257 14258 Parameter @code{loc} is optional. 14259 14260 This is a thin wrapper around the C APIs 14261 @ref{2c,,gcc_jit_context_new_comparison()} and the available kinds 14262 of comparison are documented there. 14263 @end deffn 14264 14265 There are shorter ways to spell the various specific kinds of binary 14266 operation: 14267 14268 @geindex gccjit;;context;;new_eq (C++ function) 14269 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2cd}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ce}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2cf}@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{2d0} 14270 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14271 @end deffn 14272 14273 @geindex gccjit;;context;;new_ne (C++ function) 14274 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d3}@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{2d4} 14275 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14276 @end deffn 14277 14278 @geindex gccjit;;context;;new_lt (C++ function) 14279 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d5}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d6}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d7}@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2d8} 14280 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14281 @end deffn 14282 14283 @geindex gccjit;;context;;new_le (C++ function) 14284 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2d9}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2da}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2db}@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{2dc} 14285 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14286 @end deffn 14287 14288 @geindex gccjit;;context;;new_gt (C++ function) 14289 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2dd}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2de}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2df}@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2e0} 14290 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14291 @end deffn 14292 14293 @geindex gccjit;;context;;new_ge (C++ function) 14294 @anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2e1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2e2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2e3}@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{2e4} 14295 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 14296 @end deffn 14297 14298 The most concise way to spell them is with overloaded operators: 14299 14300 @geindex operator== (C++ function) 14301 @anchor{cp/topics/expressions _CPPv4eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2e5}@anchor{cp/topics/expressions _CPPv3eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2e6}@anchor{cp/topics/expressions _CPPv2eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2e7}@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{2e8} 14302 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator== (gccjit::rvalue a, gccjit::rvalue b) 14303 14304 @example 14305 gccjit::rvalue cond = (a == ctxt.zero (t_int)); 14306 @end example 14307 @end deffn 14308 14309 @geindex operator!= (C++ function) 14310 @anchor{cp/topics/expressions _CPPv4neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2e9}@anchor{cp/topics/expressions _CPPv3neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ea}@anchor{cp/topics/expressions _CPPv2neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2eb}@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{2ec} 14311 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator!= (gccjit::rvalue a, gccjit::rvalue b) 14312 14313 @example 14314 gccjit::rvalue cond = (i != j); 14315 @end example 14316 @end deffn 14317 14318 @geindex operator< (C++ function) 14319 @anchor{cp/topics/expressions _CPPv4ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ed}@anchor{cp/topics/expressions _CPPv3ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ee}@anchor{cp/topics/expressions _CPPv2ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ef}@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{2f0} 14320 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator< (gccjit::rvalue a, gccjit::rvalue b) 14321 14322 @example 14323 gccjit::rvalue cond = i < n; 14324 @end example 14325 @end deffn 14326 14327 @geindex operator<= (C++ function) 14328 @anchor{cp/topics/expressions _CPPv4leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f1}@anchor{cp/topics/expressions _CPPv3leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f2}@anchor{cp/topics/expressions _CPPv2leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f3}@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{2f4} 14329 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator<= (gccjit::rvalue a, gccjit::rvalue b) 14330 14331 @example 14332 gccjit::rvalue cond = i <= n; 14333 @end example 14334 @end deffn 14335 14336 @geindex operator> (C++ function) 14337 @anchor{cp/topics/expressions _CPPv4gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f5}@anchor{cp/topics/expressions _CPPv3gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f6}@anchor{cp/topics/expressions _CPPv2gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f7}@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{2f8} 14338 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator> (gccjit::rvalue a, gccjit::rvalue b) 14339 14340 @example 14341 gccjit::rvalue cond = (ch > limit); 14342 @end example 14343 @end deffn 14344 14345 @geindex operator>= (C++ function) 14346 @anchor{cp/topics/expressions _CPPv4geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2f9}@anchor{cp/topics/expressions _CPPv3geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2fa}@anchor{cp/topics/expressions _CPPv2geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2fb}@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{2fc} 14347 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} operator>= (gccjit::rvalue a, gccjit::rvalue b) 14348 14349 @example 14350 gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100)); 14351 @end example 14352 @end deffn 14353 14354 @c TODO: beyond this point 14355 14356 @node Function calls<2>,Function pointers<3>,Comparisons<2>,Rvalues<2> 14357 @anchor{cp/topics/expressions function-calls}@anchor{2fd} 14358 @subsubsection Function calls 14359 14360 14361 @geindex gcc_jit_context_new_call (C++ function) 14362 @anchor{cp/topics/expressions _CPPv424gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2fe}@anchor{cp/topics/expressions _CPPv324gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2ff}@anchor{cp/topics/expressions _CPPv224gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{300}@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{301} 14363 @deffn {C++ Function} gcc_jit_rvalue *gcc_jit_context_new_call (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_function *func, int numargs, gcc_jit_rvalue **args) 14364 14365 Given a function and the given table of argument rvalues, construct a 14366 call to the function, with the result as an rvalue. 14367 14368 @cartouche 14369 @quotation Note 14370 @code{gccjit::context::new_call()} merely builds a 14371 @ref{17e,,gccjit;;rvalue} i.e. an expression that can be evaluated, 14372 perhaps as part of a more complicated expression. 14373 The call @emph{wont} happen unless you add a statement to a function 14374 that evaluates the expression. 14375 14376 For example, if you want to call a function and discard the result 14377 (or to call a function with @code{void} return type), use 14378 @ref{302,,gccjit;;block;;add_eval()}: 14379 14380 @example 14381 /* Add "(void)printf (arg0, arg1);". */ 14382 block.add_eval (ctxt.new_call (printf_func, arg0, arg1)); 14383 @end example 14384 @end quotation 14385 @end cartouche 14386 @end deffn 14387 14388 @node Function pointers<3>,Type-coercion<2>,Function calls<2>,Rvalues<2> 14389 @anchor{cp/topics/expressions function-pointers}@anchor{303} 14390 @subsubsection Function pointers 14391 14392 14393 @geindex gccjit;;function;;get_address (C++ function) 14394 @anchor{cp/topics/expressions _CPPv4N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{304}@anchor{cp/topics/expressions _CPPv3N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{305}@anchor{cp/topics/expressions _CPPv2N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{306}@anchor{cp/topics/expressions gccjit function get_address__gccjit location}@anchor{307} 14395 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{18c,,function}::get_address (gccjit::location loc) 14396 14397 Get the address of a function as an rvalue, of function pointer 14398 type. 14399 @end deffn 14400 14401 @node Type-coercion<2>,,Function pointers<3>,Rvalues<2> 14402 @anchor{cp/topics/expressions type-coercion}@anchor{308} 14403 @subsubsection Type-coercion 14404 14405 14406 @geindex gccjit;;context;;new_cast (C++ function) 14407 @anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{309}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{30a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{30b}@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{30c} 14408 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{175,,context}::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc) 14409 14410 Given an rvalue of T, construct another rvalue of another type. 14411 14412 Currently only a limited set of conversions are possible: 14413 14414 @quotation 14415 14416 14417 @itemize * 14418 14419 @item 14420 int <-> float 14421 14422 @item 14423 int <-> bool 14424 14425 @item 14426 P* <-> Q*, for pointer types P and Q 14427 @end itemize 14428 @end quotation 14429 @end deffn 14430 14431 @node Lvalues<2>,Working with pointers structs and unions<2>,Rvalues<2>,Expressions<2> 14432 @anchor{cp/topics/expressions lvalues}@anchor{30d} 14433 @subsubsection Lvalues 14434 14435 14436 @geindex gccjit;;lvalue (C++ class) 14437 @anchor{cp/topics/expressions _CPPv4N6gccjit6lvalueE}@anchor{187}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalueE}@anchor{30e}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalueE}@anchor{30f}@anchor{cp/topics/expressions gccjit lvalue}@anchor{310} 14438 @deffn {C++ Class} gccjit::lvalue 14439 @end deffn 14440 14441 An lvalue is something that can of the @emph{left}-hand side of an assignment: 14442 a storage area (such as a variable). It is a subclass of 14443 @ref{17e,,gccjit;;rvalue}, where the rvalue is computed by reading from the 14444 storage area. 14445 14446 It iss a thin wrapper around @ref{24,,gcc_jit_lvalue *} from the C API. 14447 14448 @geindex gccjit;;lvalue;;get_address (C++ function) 14449 @anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{311}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{312}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{313}@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{314} 14450 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{187,,lvalue}::get_address (gccjit::location loc) 14451 14452 Take the address of an lvalue; analogous to: 14453 14454 @example 14455 &(EXPR) 14456 @end example 14457 14458 in C. 14459 14460 Parameter loc is optional. 14461 @end deffn 14462 14463 @menu 14464 * Global variables: Global variables<2>. 14465 14466 @end menu 14467 14468 @node Global variables<2>,,,Lvalues<2> 14469 @anchor{cp/topics/expressions global-variables}@anchor{315} 14470 @subsubsection Global variables 14471 14472 14473 @geindex gccjit;;context;;new_global (C++ function) 14474 @anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{316}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{317}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{318}@anchor{cp/topics/expressions gccjit context new_global__gcc_jit_global_kind gccjit type cCP gccjit location}@anchor{319} 14475 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{175,,context}::new_global (enum gcc_jit_global_kind, gccjit::type type, const char *name, gccjit::location loc) 14476 14477 Add a new global variable of the given type and name to the context. 14478 14479 This is a thin wrapper around @ref{f5,,gcc_jit_context_new_global()} from 14480 the C API; the kind parameter has the same meaning as there. 14481 @end deffn 14482 14483 @node Working with pointers structs and unions<2>,,Lvalues<2>,Expressions<2> 14484 @anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{31a} 14485 @subsubsection Working with pointers, structs and unions 14486 14487 14488 @geindex gccjit;;rvalue;;dereference (C++ function) 14489 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{31b}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{31c}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{31d}@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{31e} 14490 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{17e,,rvalue}::dereference (gccjit::location loc) 14491 14492 Given an rvalue of pointer type @code{T *}, dereferencing the pointer, 14493 getting an lvalue of type @code{T}. Analogous to: 14494 14495 @example 14496 *(EXPR) 14497 @end example 14498 14499 in C. 14500 14501 Parameter loc is optional. 14502 @end deffn 14503 14504 If you dont need to specify the location, this can also be expressed using 14505 an overloaded operator: 14506 14507 @geindex gccjit;;rvalue;;operator* (C++ function) 14508 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvaluemlEv}@anchor{31f}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvaluemlEv}@anchor{320}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvaluemlEv}@anchor{321}@anchor{cp/topics/expressions gccjit rvalue mul-operator}@anchor{322} 14509 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{17e,,rvalue}::operator* () 14510 14511 @example 14512 gccjit::lvalue content = *ptr; 14513 @end example 14514 @end deffn 14515 14516 Field access is provided separately for both lvalues and rvalues: 14517 14518 @geindex gccjit;;lvalue;;access_field (C++ function) 14519 @anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{323}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{324}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{325}@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{326} 14520 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{187,,lvalue}::access_field (gccjit::field field, gccjit::location loc) 14521 14522 Given an lvalue of struct or union type, access the given field, 14523 getting an lvalue of the fields type. Analogous to: 14524 14525 @example 14526 (EXPR).field = ...; 14527 @end example 14528 14529 in C. 14530 @end deffn 14531 14532 @geindex gccjit;;rvalue;;access_field (C++ function) 14533 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{327}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{328}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{329}@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{32a} 14534 @deffn {C++ Function} gccjit::@ref{17e,,rvalue} gccjit::@ref{17e,,rvalue}::access_field (gccjit::field field, gccjit::location loc) 14535 14536 Given an rvalue of struct or union type, access the given field 14537 as an rvalue. Analogous to: 14538 14539 @example 14540 (EXPR).field 14541 @end example 14542 14543 in C. 14544 @end deffn 14545 14546 @geindex gccjit;;rvalue;;dereference_field (C++ function) 14547 @anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{32b}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{32c}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{32d}@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{32e} 14548 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{17e,,rvalue}::dereference_field (gccjit::field field, gccjit::location loc) 14549 14550 Given an rvalue of pointer type @code{T *} where T is of struct or union 14551 type, access the given field as an lvalue. Analogous to: 14552 14553 @example 14554 (EXPR)->field 14555 @end example 14556 14557 in C, itself equivalent to @code{(*EXPR).FIELD}. 14558 @end deffn 14559 14560 @geindex gccjit;;context;;new_array_access (C++ function) 14561 @anchor{cp/topics/expressions _CPPv4N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{32f}@anchor{cp/topics/expressions _CPPv3N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{330}@anchor{cp/topics/expressions _CPPv2N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{331}@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{332} 14562 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{175,,context}::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc) 14563 14564 Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at 14565 the given index, using standard C array indexing rules i.e. each 14566 increment of @code{index} corresponds to @code{sizeof(T)} bytes. 14567 Analogous to: 14568 14569 @example 14570 PTR[INDEX] 14571 @end example 14572 14573 in C (or, indeed, to @code{PTR + INDEX}). 14574 14575 Parameter loc is optional. 14576 @end deffn 14577 14578 For array accesses where you dont need to specify a @ref{19b,,gccjit;;location}, 14579 two overloaded operators are available: 14580 14581 @quotation 14582 14583 gccjit::lvalue gccjit::rvalue::operator[] (gccjit::rvalue index) 14584 14585 @example 14586 gccjit::lvalue element = array[idx]; 14587 @end example 14588 14589 gccjit::lvalue gccjit::rvalue::operator[] (int index) 14590 14591 @example 14592 gccjit::lvalue element = array[0]; 14593 @end example 14594 @end quotation 14595 14596 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 14597 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 14598 @c 14599 @c This is free software: you can redistribute it and/or modify it 14600 @c under the terms of the GNU General Public License as published by 14601 @c the Free Software Foundation, either version 3 of the License, or 14602 @c (at your option) any later version. 14603 @c 14604 @c This program is distributed in the hope that it will be useful, but 14605 @c WITHOUT ANY WARRANTY; without even the implied warranty of 14606 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14607 @c General Public License for more details. 14608 @c 14609 @c You should have received a copy of the GNU General Public License 14610 @c along with this program. If not, see 14611 @c <https://www.gnu.org/licenses/>. 14612 14613 @node Creating and using functions<2>,Source Locations<2>,Expressions<2>,Topic Reference<2> 14614 @anchor{cp/topics/functions doc}@anchor{333}@anchor{cp/topics/functions creating-and-using-functions}@anchor{334} 14615 @subsection Creating and using functions 14616 14617 14618 @menu 14619 * Params: Params<2>. 14620 * Functions: Functions<2>. 14621 * Blocks: Blocks<2>. 14622 * Statements: Statements<2>. 14623 14624 @end menu 14625 14626 @node Params<2>,Functions<2>,,Creating and using functions<2> 14627 @anchor{cp/topics/functions params}@anchor{335} 14628 @subsubsection Params 14629 14630 14631 @geindex gccjit;;param (C++ class) 14632 @anchor{cp/topics/functions _CPPv4N6gccjit5paramE}@anchor{188}@anchor{cp/topics/functions _CPPv3N6gccjit5paramE}@anchor{336}@anchor{cp/topics/functions _CPPv2N6gccjit5paramE}@anchor{337}@anchor{cp/topics/functions gccjit param}@anchor{338} 14633 @deffn {C++ Class} gccjit::param 14634 14635 A @cite{gccjit::param} represents a parameter to a function. 14636 @end deffn 14637 14638 @geindex gccjit;;context;;new_param (C++ function) 14639 @anchor{cp/topics/functions _CPPv4N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{17c}@anchor{cp/topics/functions _CPPv3N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{339}@anchor{cp/topics/functions _CPPv2N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{33a}@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{33b} 14640 @deffn {C++ Function} gccjit::@ref{188,,param} gccjit::@ref{175,,context}::new_param (gccjit::type type, const char *name, gccjit::location loc) 14641 14642 In preparation for creating a function, create a new parameter of the 14643 given type and name. 14644 @end deffn 14645 14646 @ref{188,,gccjit;;param} is a subclass of @ref{187,,gccjit;;lvalue} (and thus 14647 of @ref{17e,,gccjit;;rvalue} and @ref{17a,,gccjit;;object}). It is a thin 14648 wrapper around the C APIs @ref{25,,gcc_jit_param *}. 14649 14650 @node Functions<2>,Blocks<2>,Params<2>,Creating and using functions<2> 14651 @anchor{cp/topics/functions functions}@anchor{33c} 14652 @subsubsection Functions 14653 14654 14655 @geindex gccjit;;function (C++ class) 14656 @anchor{cp/topics/functions _CPPv4N6gccjit8functionE}@anchor{18c}@anchor{cp/topics/functions _CPPv3N6gccjit8functionE}@anchor{33d}@anchor{cp/topics/functions _CPPv2N6gccjit8functionE}@anchor{33e}@anchor{cp/topics/functions gccjit function}@anchor{33f} 14657 @deffn {C++ Class} gccjit::function 14658 14659 A @cite{gccjit::function} represents a function - either one that were 14660 creating ourselves, or one that were referencing. 14661 @end deffn 14662 14663 @geindex gccjit;;context;;new_function (C++ function) 14664 @anchor{cp/topics/functions _CPPv4N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{340}@anchor{cp/topics/functions _CPPv3N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{341}@anchor{cp/topics/functions _CPPv2N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{342}@anchor{cp/topics/functions gccjit context new_function__gcc_jit_function_kind gccjit type cCP std vector param R i gccjit location}@anchor{343} 14665 @deffn {C++ Function} gccjit::@ref{18c,,function} gccjit::@ref{175,,context}::new_function (enum gcc_jit_function_kind, gccjit::type return_type, const char *name, std::vector<param> ¶ms, int is_variadic, gccjit::location loc) 14666 14667 Create a gcc_jit_function with the given name and parameters. 14668 14669 Parameters is_variadic and loc are optional. 14670 14671 This is a wrapper around the C APIs @ref{11,,gcc_jit_context_new_function()}. 14672 @end deffn 14673 14674 @geindex gccjit;;context;;get_builtin_function (C++ function) 14675 @anchor{cp/topics/functions _CPPv4N6gccjit7context20get_builtin_functionEPKc}@anchor{344}@anchor{cp/topics/functions _CPPv3N6gccjit7context20get_builtin_functionEPKc}@anchor{345}@anchor{cp/topics/functions _CPPv2N6gccjit7context20get_builtin_functionEPKc}@anchor{346}@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{347} 14676 @deffn {C++ Function} gccjit::@ref{18c,,function} gccjit::@ref{175,,context}::get_builtin_function (const char *name) 14677 14678 This is a wrapper around the C APIs 14679 @ref{10e,,gcc_jit_context_get_builtin_function()}. 14680 @end deffn 14681 14682 @geindex gccjit;;function;;get_param (C++ function) 14683 @anchor{cp/topics/functions _CPPv4NK6gccjit8function9get_paramEi}@anchor{348}@anchor{cp/topics/functions _CPPv3NK6gccjit8function9get_paramEi}@anchor{349}@anchor{cp/topics/functions _CPPv2NK6gccjit8function9get_paramEi}@anchor{34a}@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{34b} 14684 @deffn {C++ Function} gccjit::@ref{188,,param} gccjit::@ref{18c,,function}::get_param (int index) const 14685 14686 Get the param of the given index (0-based). 14687 @end deffn 14688 14689 @geindex gccjit;;function;;dump_to_dot (C++ function) 14690 @anchor{cp/topics/functions _CPPv4N6gccjit8function11dump_to_dotEPKc}@anchor{194}@anchor{cp/topics/functions _CPPv3N6gccjit8function11dump_to_dotEPKc}@anchor{34c}@anchor{cp/topics/functions _CPPv2N6gccjit8function11dump_to_dotEPKc}@anchor{34d}@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{34e} 14691 @deffn {C++ Function} void gccjit::@ref{18c,,function}::dump_to_dot (const char *path) 14692 14693 Emit the function in graphviz format to the given path. 14694 @end deffn 14695 14696 @geindex gccjit;;function;;new_local (C++ function) 14697 @anchor{cp/topics/functions _CPPv4N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{189}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{34f}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{350}@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{351} 14698 @deffn {C++ Function} gccjit::@ref{187,,lvalue} gccjit::@ref{18c,,function}::new_local (gccjit::type type, const char *name, gccjit::location loc) 14699 14700 Create a new local variable within the function, of the given type and 14701 name. 14702 @end deffn 14703 14704 @node Blocks<2>,Statements<2>,Functions<2>,Creating and using functions<2> 14705 @anchor{cp/topics/functions blocks}@anchor{352} 14706 @subsubsection Blocks 14707 14708 14709 @geindex gccjit;;block (C++ class) 14710 @anchor{cp/topics/functions _CPPv4N6gccjit5blockE}@anchor{18b}@anchor{cp/topics/functions _CPPv3N6gccjit5blockE}@anchor{353}@anchor{cp/topics/functions _CPPv2N6gccjit5blockE}@anchor{354}@anchor{cp/topics/functions gccjit block}@anchor{355} 14711 @deffn {C++ Class} gccjit::block 14712 14713 A @cite{gccjit::block} represents a basic block within a function i.e. a 14714 sequence of statements with a single entry point and a single exit 14715 point. 14716 14717 @ref{18b,,gccjit;;block} is a subclass of @ref{17a,,gccjit;;object}. 14718 14719 The first basic block that you create within a function will 14720 be the entrypoint. 14721 14722 Each basic block that you create within a function must be 14723 terminated, either with a conditional, a jump, a return, or 14724 a switch. 14725 14726 Its legal to have multiple basic blocks that return within 14727 one function. 14728 @end deffn 14729 14730 @geindex gccjit;;function;;new_block (C++ function) 14731 @anchor{cp/topics/functions _CPPv4N6gccjit8function9new_blockEPKc}@anchor{356}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_blockEPKc}@anchor{357}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_blockEPKc}@anchor{358}@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{359} 14732 @deffn {C++ Function} gccjit::@ref{18b,,block} gccjit::@ref{18c,,function}::new_block (const char *name) 14733 14734 Create a basic block of the given name. The name may be NULL, but 14735 providing meaningful names is often helpful when debugging: it may 14736 show up in dumps of the internal representation, and in error 14737 messages. 14738 @end deffn 14739 14740 @node Statements<2>,,Blocks<2>,Creating and using functions<2> 14741 @anchor{cp/topics/functions statements}@anchor{35a} 14742 @subsubsection Statements 14743 14744 14745 @geindex gccjit;;block;;add_eval (C++ function) 14746 @anchor{cp/topics/functions _CPPv4N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{302}@anchor{cp/topics/functions _CPPv3N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{35b}@anchor{cp/topics/functions _CPPv2N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{35c}@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{35d} 14747 @deffn {C++ Function} void gccjit::@ref{18b,,block}::add_eval (gccjit::rvalue rvalue, gccjit::location loc) 14748 14749 Add evaluation of an rvalue, discarding the result 14750 (e.g. a function call that returns void). 14751 14752 This is equivalent to this C code: 14753 14754 @example 14755 (void)expression; 14756 @end example 14757 @end deffn 14758 14759 @geindex gccjit;;block;;add_assignment (C++ function) 14760 @anchor{cp/topics/functions _CPPv4N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{18d}@anchor{cp/topics/functions _CPPv3N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{35e}@anchor{cp/topics/functions _CPPv2N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{35f}@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{360} 14761 @deffn {C++ Function} void gccjit::@ref{18b,,block}::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc) 14762 14763 Add evaluation of an rvalue, assigning the result to the given 14764 lvalue. 14765 14766 This is roughly equivalent to this C code: 14767 14768 @example 14769 lvalue = rvalue; 14770 @end example 14771 @end deffn 14772 14773 @geindex gccjit;;block;;add_assignment_op (C++ function) 14774 @anchor{cp/topics/functions _CPPv4N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{191}@anchor{cp/topics/functions _CPPv3N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{361}@anchor{cp/topics/functions _CPPv2N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{362}@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue gcc_jit_binary_op gccjit rvalue gccjit location}@anchor{363} 14775 @deffn {C++ Function} void gccjit::@ref{18b,,block}::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc) 14776 14777 Add evaluation of an rvalue, using the result to modify an 14778 lvalue. 14779 14780 This is analogous to += and friends: 14781 14782 @example 14783 lvalue += rvalue; 14784 lvalue *= rvalue; 14785 lvalue /= rvalue; 14786 @end example 14787 14788 etc. For example: 14789 14790 @example 14791 /* "i++" */ 14792 loop_body.add_assignment_op ( 14793 i, 14794 GCC_JIT_BINARY_OP_PLUS, 14795 ctxt.one (int_type)); 14796 @end example 14797 @end deffn 14798 14799 @geindex gccjit;;block;;add_comment (C++ function) 14800 @anchor{cp/topics/functions _CPPv4N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{19d}@anchor{cp/topics/functions _CPPv3N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{364}@anchor{cp/topics/functions _CPPv2N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{365}@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{366} 14801 @deffn {C++ Function} void gccjit::@ref{18b,,block}::add_comment (const char *text, gccjit::location loc) 14802 14803 Add a no-op textual comment to the internal representation of the 14804 code. It will be optimized away, but will be visible in the dumps 14805 seen via @ref{66,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} 14806 and @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, 14807 and thus may be of use when debugging how your projects internal 14808 representation gets converted to the libgccjit IR. 14809 14810 Parameter loc is optional. 14811 @end deffn 14812 14813 @geindex gccjit;;block;;end_with_conditional (C++ function) 14814 @anchor{cp/topics/functions _CPPv4N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{190}@anchor{cp/topics/functions _CPPv3N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{367}@anchor{cp/topics/functions _CPPv2N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{368}@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{369} 14815 @deffn {C++ Function} void gccjit::@ref{18b,,block}::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc) 14816 14817 Terminate a block by adding evaluation of an rvalue, branching on the 14818 result to the appropriate successor block. 14819 14820 This is roughly equivalent to this C code: 14821 14822 @example 14823 if (boolval) 14824 goto on_true; 14825 else 14826 goto on_false; 14827 @end example 14828 14829 block, boolval, on_true, and on_false must be non-NULL. 14830 @end deffn 14831 14832 @geindex gccjit;;block;;end_with_jump (C++ function) 14833 @anchor{cp/topics/functions _CPPv4N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{36a}@anchor{cp/topics/functions _CPPv3N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{36b}@anchor{cp/topics/functions _CPPv2N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{36c}@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{36d} 14834 @deffn {C++ Function} void gccjit::@ref{18b,,block}::end_with_jump (gccjit::block target, gccjit::location loc) 14835 14836 Terminate a block by adding a jump to the given target block. 14837 14838 This is roughly equivalent to this C code: 14839 14840 @example 14841 goto target; 14842 @end example 14843 @end deffn 14844 14845 @geindex gccjit;;block;;end_with_return (C++ function) 14846 @anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{36e}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{36f}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{370}@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{371} 14847 @deffn {C++ Function} void gccjit::@ref{18b,,block}::end_with_return (gccjit::rvalue rvalue, gccjit::location loc) 14848 14849 Terminate a block. 14850 14851 Both params are optional. 14852 14853 An rvalue must be provided for a function returning non-void, and 14854 must not be provided by a function returning @cite{void}. 14855 14856 If an rvalue is provided, the block is terminated by evaluating the 14857 rvalue and returning the value. 14858 14859 This is roughly equivalent to this C code: 14860 14861 @example 14862 return expression; 14863 @end example 14864 14865 If an rvalue is not provided, the block is terminated by adding a 14866 valueless return, for use within a function with void return type. 14867 14868 This is equivalent to this C code: 14869 14870 @example 14871 return; 14872 @end example 14873 @end deffn 14874 14875 @geindex gccjit;;block;;end_with_switch (C++ function) 14876 @anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{372}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{373}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{374}@anchor{cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location}@anchor{375} 14877 @deffn {C++ Function} void gccjit::@ref{18b,,block}::end_with_switch (gccjit::rvalue expr, gccjit::block default_block, std::vector<gccjit::case_> cases, gccjit::location loc) 14878 14879 Terminate a block by adding evalation of an rvalue, then performing 14880 a multiway branch. 14881 14882 This is roughly equivalent to this C code: 14883 14884 @example 14885 switch (expr) 14886 @{ 14887 default: 14888 goto default_block; 14889 14890 case C0.min_value ... C0.max_value: 14891 goto C0.dest_block; 14892 14893 case C1.min_value ... C1.max_value: 14894 goto C1.dest_block; 14895 14896 ...etc... 14897 14898 case C[N - 1].min_value ... C[N - 1].max_value: 14899 goto C[N - 1].dest_block; 14900 @} 14901 @end example 14902 14903 @code{expr} must be of the same integer type as all of the @code{min_value} 14904 and @code{max_value} within the cases. 14905 14906 The ranges of the cases must not overlap (or have duplicate 14907 values). 14908 14909 The API entrypoints relating to switch statements and cases: 14910 14911 @quotation 14912 14913 14914 @itemize * 14915 14916 @item 14917 @ref{372,,gccjit;;block;;end_with_switch()} 14918 14919 @item 14920 @code{gccjit::context::new_case()} 14921 @end itemize 14922 @end quotation 14923 14924 were added in @ref{11f,,LIBGCCJIT_ABI_3}; you can test for their presence 14925 using 14926 14927 @example 14928 #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS 14929 @end example 14930 14931 A @cite{gccjit::case_} represents a case within a switch statement, and 14932 is created within a particular @ref{175,,gccjit;;context} using 14933 @code{gccjit::context::new_case()}. It is a subclass of 14934 @ref{17a,,gccjit;;object}. 14935 14936 Each case expresses a multivalued range of integer values. You 14937 can express single-valued cases by passing in the same value for 14938 both @cite{min_value} and @cite{max_value}. 14939 14940 Heres an example of creating a switch statement: 14941 14942 @quotation 14943 14944 @example 14945 14946 void 14947 create_code (gcc_jit_context *c_ctxt, void *user_data) 14948 @{ 14949 /* Let's try to inject the equivalent of: 14950 int 14951 test_switch (int x) 14952 @{ 14953 switch (x) 14954 @{ 14955 case 0 ... 5: 14956 return 3; 14957 14958 case 25 ... 27: 14959 return 4; 14960 14961 case -42 ... -17: 14962 return 83; 14963 14964 case 40: 14965 return 8; 14966 14967 default: 14968 return 10; 14969 @} 14970 @} 14971 */ 14972 gccjit::context ctxt (c_ctxt); 14973 gccjit::type t_int = ctxt.get_type (GCC_JIT_TYPE_INT); 14974 gccjit::type return_type = t_int; 14975 gccjit::param x = ctxt.new_param (t_int, "x"); 14976 std::vector <gccjit::param> params; 14977 params.push_back (x); 14978 gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 14979 return_type, 14980 "test_switch", 14981 params, 0); 14982 14983 gccjit::block b_initial = func.new_block ("initial"); 14984 14985 gccjit::block b_default = func.new_block ("default"); 14986 gccjit::block b_case_0_5 = func.new_block ("case_0_5"); 14987 gccjit::block b_case_25_27 = func.new_block ("case_25_27"); 14988 gccjit::block b_case_m42_m17 = func.new_block ("case_m42_m17"); 14989 gccjit::block b_case_40 = func.new_block ("case_40"); 14990 14991 std::vector <gccjit::case_> cases; 14992 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 0), 14993 ctxt.new_rvalue (t_int, 5), 14994 b_case_0_5)); 14995 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 25), 14996 ctxt.new_rvalue (t_int, 27), 14997 b_case_25_27)); 14998 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, -42), 14999 ctxt.new_rvalue (t_int, -17), 15000 b_case_m42_m17)); 15001 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 40), 15002 ctxt.new_rvalue (t_int, 40), 15003 b_case_40)); 15004 b_initial.end_with_switch (x, 15005 b_default, 15006 cases); 15007 15008 b_case_0_5.end_with_return (ctxt.new_rvalue (t_int, 3)); 15009 b_case_25_27.end_with_return (ctxt.new_rvalue (t_int, 4)); 15010 b_case_m42_m17.end_with_return (ctxt.new_rvalue (t_int, 83)); 15011 b_case_40.end_with_return (ctxt.new_rvalue (t_int, 8)); 15012 b_default.end_with_return (ctxt.new_rvalue (t_int, 10)); 15013 @} 15014 15015 @end example 15016 @end quotation 15017 @end deffn 15018 15019 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 15020 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 15021 @c 15022 @c This is free software: you can redistribute it and/or modify it 15023 @c under the terms of the GNU General Public License as published by 15024 @c the Free Software Foundation, either version 3 of the License, or 15025 @c (at your option) any later version. 15026 @c 15027 @c This program is distributed in the hope that it will be useful, but 15028 @c WITHOUT ANY WARRANTY; without even the implied warranty of 15029 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15030 @c General Public License for more details. 15031 @c 15032 @c You should have received a copy of the GNU General Public License 15033 @c along with this program. If not, see 15034 @c <https://www.gnu.org/licenses/>. 15035 15036 @node Source Locations<2>,Compiling a context<2>,Creating and using functions<2>,Topic Reference<2> 15037 @anchor{cp/topics/locations doc}@anchor{376}@anchor{cp/topics/locations source-locations}@anchor{377} 15038 @subsection Source Locations 15039 15040 15041 @geindex gccjit;;location (C++ class) 15042 @anchor{cp/topics/locations _CPPv4N6gccjit8locationE}@anchor{19b}@anchor{cp/topics/locations _CPPv3N6gccjit8locationE}@anchor{378}@anchor{cp/topics/locations _CPPv2N6gccjit8locationE}@anchor{379}@anchor{cp/topics/locations gccjit location}@anchor{37a} 15043 @deffn {C++ Class} gccjit::location 15044 15045 A @cite{gccjit::location} encapsulates a source code location, so that 15046 you can (optionally) associate locations in your language with 15047 statements in the JIT-compiled code, allowing the debugger to 15048 single-step through your language. 15049 15050 @cite{gccjit::location} instances are optional: you can always omit them 15051 from any C++ API entrypoint accepting one. 15052 15053 You can construct them using @ref{1a1,,gccjit;;context;;new_location()}. 15054 15055 You need to enable @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 15056 @ref{175,,gccjit;;context} for these locations to actually be usable by 15057 the debugger: 15058 15059 @example 15060 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); 15061 @end example 15062 @end deffn 15063 15064 @geindex gccjit;;context;;new_location (C++ function) 15065 @anchor{cp/topics/locations _CPPv4N6gccjit7context12new_locationEPKcii}@anchor{1a1}@anchor{cp/topics/locations _CPPv3N6gccjit7context12new_locationEPKcii}@anchor{37b}@anchor{cp/topics/locations _CPPv2N6gccjit7context12new_locationEPKcii}@anchor{37c}@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{37d} 15066 @deffn {C++ Function} gccjit::@ref{19b,,location} gccjit::@ref{175,,context}::new_location (const char *filename, int line, int column) 15067 15068 Create a @cite{gccjit::location} instance representing the given source 15069 location. 15070 @end deffn 15071 15072 @menu 15073 * Faking it: Faking it<2>. 15074 15075 @end menu 15076 15077 @node Faking it<2>,,,Source Locations<2> 15078 @anchor{cp/topics/locations faking-it}@anchor{37e} 15079 @subsubsection Faking it 15080 15081 15082 If you dont have source code for your internal representation, but need 15083 to debug, you can generate a C-like representation of the functions in 15084 your context using @ref{1c0,,gccjit;;context;;dump_to_file()}: 15085 15086 @example 15087 ctxt.dump_to_file ("/tmp/something.c", 15088 1 /* update_locations */); 15089 @end example 15090 15091 This will dump C-like code to the given path. If the @cite{update_locations} 15092 argument is true, this will also set up @cite{gccjit::location} information 15093 throughout the context, pointing at the dump file as if it were a source 15094 file, giving you @emph{something} you can step through in the debugger. 15095 15096 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 15097 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 15098 @c 15099 @c This is free software: you can redistribute it and/or modify it 15100 @c under the terms of the GNU General Public License as published by 15101 @c the Free Software Foundation, either version 3 of the License, or 15102 @c (at your option) any later version. 15103 @c 15104 @c This program is distributed in the hope that it will be useful, but 15105 @c WITHOUT ANY WARRANTY; without even the implied warranty of 15106 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15107 @c General Public License for more details. 15108 @c 15109 @c You should have received a copy of the GNU General Public License 15110 @c along with this program. If not, see 15111 @c <https://www.gnu.org/licenses/>. 15112 15113 @node Compiling a context<2>,Using Assembly Language with libgccjit++,Source Locations<2>,Topic Reference<2> 15114 @anchor{cp/topics/compilation doc}@anchor{37f}@anchor{cp/topics/compilation compiling-a-context}@anchor{380} 15115 @subsection Compiling a context 15116 15117 15118 Once populated, a @ref{175,,gccjit;;context} can be compiled to 15119 machine code, either in-memory via @ref{17f,,gccjit;;context;;compile()} or 15120 to disk via @ref{381,,gccjit;;context;;compile_to_file()}. 15121 15122 You can compile a context multiple times (using either form of 15123 compilation), although any errors that occur on the context will 15124 prevent any future compilation of that context. 15125 15126 @menu 15127 * In-memory compilation: In-memory compilation<2>. 15128 * Ahead-of-time compilation: Ahead-of-time compilation<2>. 15129 15130 @end menu 15131 15132 @node In-memory compilation<2>,Ahead-of-time compilation<2>,,Compiling a context<2> 15133 @anchor{cp/topics/compilation in-memory-compilation}@anchor{382} 15134 @subsubsection In-memory compilation 15135 15136 15137 @geindex gccjit;;context;;compile (C++ function) 15138 @anchor{cp/topics/compilation _CPPv4N6gccjit7context7compileEv}@anchor{17f}@anchor{cp/topics/compilation _CPPv3N6gccjit7context7compileEv}@anchor{383}@anchor{cp/topics/compilation _CPPv2N6gccjit7context7compileEv}@anchor{384}@anchor{cp/topics/compilation gccjit context compile}@anchor{385} 15139 @deffn {C++ Function} gcc_jit_result *gccjit::@ref{175,,context}::compile () 15140 15141 This calls into GCC and builds the code, returning a 15142 @cite{gcc_jit_result *}. 15143 15144 This is a thin wrapper around the 15145 @ref{15,,gcc_jit_context_compile()} API entrypoint. 15146 @end deffn 15147 15148 @node Ahead-of-time compilation<2>,,In-memory compilation<2>,Compiling a context<2> 15149 @anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{386} 15150 @subsubsection Ahead-of-time compilation 15151 15152 15153 Although libgccjit is primarily aimed at just-in-time compilation, it 15154 can also be used for implementing more traditional ahead-of-time 15155 compilers, via the @ref{381,,gccjit;;context;;compile_to_file()} method. 15156 15157 @geindex gccjit;;context;;compile_to_file (C++ function) 15158 @anchor{cp/topics/compilation _CPPv4N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{381}@anchor{cp/topics/compilation _CPPv3N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{387}@anchor{cp/topics/compilation _CPPv2N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{388}@anchor{cp/topics/compilation gccjit context compile_to_file__gcc_jit_output_kind cCP}@anchor{389} 15159 @deffn {C++ Function} void gccjit::@ref{175,,context}::compile_to_file (enum gcc_jit_output_kind, const char *output_path) 15160 15161 Compile the @ref{175,,gccjit;;context} to a file of the given 15162 kind. 15163 15164 This is a thin wrapper around the 15165 @ref{4a,,gcc_jit_context_compile_to_file()} API entrypoint. 15166 @end deffn 15167 15168 @c Copyright (C) 2020-2022 Free Software Foundation, Inc. 15169 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 15170 @c 15171 @c This is free software: you can redistribute it and/or modify it 15172 @c under the terms of the GNU General Public License as published by 15173 @c the Free Software Foundation, either version 3 of the License, or 15174 @c (at your option) any later version. 15175 @c 15176 @c This program is distributed in the hope that it will be useful, but 15177 @c WITHOUT ANY WARRANTY; without even the implied warranty of 15178 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15179 @c General Public License for more details. 15180 @c 15181 @c You should have received a copy of the GNU General Public License 15182 @c along with this program. If not, see 15183 @c <https://www.gnu.org/licenses/>. 15184 15185 @node Using Assembly Language with libgccjit++,,Compiling a context<2>,Topic Reference<2> 15186 @anchor{cp/topics/asm doc}@anchor{38a}@anchor{cp/topics/asm using-assembly-language-with-libgccjit}@anchor{38b} 15187 @subsection Using Assembly Language with libgccjit++ 15188 15189 15190 libgccjit has some support for directly embedding assembler instructions. 15191 This is based on GCCs support for inline @code{asm} in C code, and the 15192 following assumes a familiarity with that functionality. See 15193 How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html} 15194 in GCCs documentation, the Extended Asm section in particular. 15195 15196 These entrypoints were added in @ref{151,,LIBGCCJIT_ABI_15}; you can test 15197 for their presence using 15198 15199 @quotation 15200 15201 @example 15202 #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS 15203 @end example 15204 @end quotation 15205 15206 @menu 15207 * Adding assembler instructions within a function: Adding assembler instructions within a function<2>. 15208 * Adding top-level assembler statements: Adding top-level assembler statements<2>. 15209 15210 @end menu 15211 15212 @node Adding assembler instructions within a function<2>,Adding top-level assembler statements<2>,,Using Assembly Language with libgccjit++ 15213 @anchor{cp/topics/asm adding-assembler-instructions-within-a-function}@anchor{38c} 15214 @subsubsection Adding assembler instructions within a function 15215 15216 15217 @geindex gccjit;;extended_asm (C++ class) 15218 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asmE}@anchor{38d}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asmE}@anchor{38e}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asmE}@anchor{38f}@anchor{cp/topics/asm gccjit extended_asm}@anchor{390} 15219 @deffn {C++ Class} gccjit::extended_asm 15220 15221 A @cite{gccjit::extended_asm} represents an extended @code{asm} statement: a 15222 series of low-level instructions inside a function that convert inputs 15223 to outputs. 15224 15225 @ref{38d,,gccjit;;extended_asm} is a subclass of @ref{17a,,gccjit;;object}. 15226 It is a thin wrapper around the C APIs @ref{120,,gcc_jit_extended_asm *}. 15227 15228 To avoid having an API entrypoint with a very large number of 15229 parameters, an extended @code{asm} statement is made in stages: 15230 an initial call to create the @ref{38d,,gccjit;;extended_asm}, 15231 followed by calls to add operands and set other properties of the 15232 statement. 15233 15234 There are two API entrypoints for creating a @ref{38d,,gccjit;;extended_asm}: 15235 15236 15237 @itemize * 15238 15239 @item 15240 @ref{391,,gccjit;;block;;add_extended_asm()} for an @code{asm} statement with 15241 no control flow, and 15242 15243 @item 15244 @ref{392,,gccjit;;block;;end_with_extended_asm_goto()} for an @code{asm goto}. 15245 @end itemize 15246 15247 For example, to create the equivalent of: 15248 15249 @example 15250 asm ("mov %1, %0\n\t" 15251 "add $1, %0" 15252 : "=r" (dst) 15253 : "r" (src)); 15254 @end example 15255 15256 the following API calls could be used: 15257 15258 @example 15259 block.add_extended_asm ("mov %1, %0\n\t" 15260 "add $1, %0") 15261 .add_output_operand ("=r", dst) 15262 .add_input_operand ("r", src); 15263 @end example 15264 15265 @cartouche 15266 @quotation Warning 15267 When considering the numbering of operands within an 15268 extended @code{asm} statement (e.g. the @code{%0} and @code{%1} 15269 above), the equivalent to the C syntax is followed i.e. all 15270 output operands, then all input operands, regardless of 15271 what order the calls to 15272 @ref{393,,gccjit;;extended_asm;;add_output_operand()} and 15273 @ref{394,,gccjit;;extended_asm;;add_input_operand()} were made in. 15274 @end quotation 15275 @end cartouche 15276 15277 As in the C syntax, operands can be given symbolic names to avoid having 15278 to number them. For example, to create the equivalent of: 15279 15280 @example 15281 asm ("bsfl %[aMask], %[aIndex]" 15282 : [aIndex] "=r" (Index) 15283 : [aMask] "r" (Mask) 15284 : "cc"); 15285 @end example 15286 15287 the following API calls could be used: 15288 15289 @example 15290 block.add_extended_asm ("bsfl %[aMask], %[aIndex]") 15291 .add_output_operand ("aIndex", "=r", index) 15292 .add_input_operand ("aMask", "r", mask) 15293 .add_clobber ("cc"); 15294 @end example 15295 @end deffn 15296 15297 @geindex gccjit;;block;;add_extended_asm (C++ function) 15298 @anchor{cp/topics/asm _CPPv4N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{391}@anchor{cp/topics/asm _CPPv3N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{395}@anchor{cp/topics/asm _CPPv2N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{396}@anchor{cp/topics/asm gccjit block add_extended_asm__ssCR gccjit location}@anchor{397} 15299 @deffn {C++ Function} @ref{38d,,extended_asm} gccjit::@ref{18b,,block}::add_extended_asm (const std::string &asm_template, gccjit::location loc = location()) 15300 15301 Create a @ref{38d,,gccjit;;extended_asm} for an extended @code{asm} statement 15302 with no control flow (i.e. without the @code{goto} qualifier). 15303 15304 The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate} 15305 within Cs extended @code{asm} syntax. It must be non-NULL. The call takes 15306 a copy of the underlying string, so it is valid to pass in a pointer to 15307 an on-stack buffer. 15308 @end deffn 15309 15310 @geindex gccjit;;block;;end_with_extended_asm_goto (C++ function) 15311 @anchor{cp/topics/asm _CPPv4N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{392}@anchor{cp/topics/asm _CPPv3N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{398}@anchor{cp/topics/asm _CPPv2N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{399}@anchor{cp/topics/asm gccjit block end_with_extended_asm_goto__ssCR std vector block blockP location}@anchor{39a} 15312 @deffn {C++ Function} @ref{38d,,extended_asm} gccjit::@ref{18b,,block}::end_with_extended_asm_goto (const std::string &asm_template, std::vector<block> goto_blocks, block *fallthrough_block, location loc = location()) 15313 15314 Create a @ref{38d,,gccjit;;extended_asm} for an extended @code{asm} statement 15315 that may perform jumps, and use it to terminate the given block. 15316 This is equivalent to the @code{goto} qualifier in Cs extended @code{asm} 15317 syntax. 15318 15319 For example, to create the equivalent of: 15320 15321 @example 15322 asm goto ("btl %1, %0\n\t" 15323 "jc %l[carry]" 15324 : // No outputs 15325 : "r" (p1), "r" (p2) 15326 : "cc" 15327 : carry); 15328 @end example 15329 15330 the following API calls could be used: 15331 15332 @example 15333 const char *asm_template = 15334 (use_name 15335 ? /* Label referred to by name: "%l[carry]". */ 15336 ("btl %1, %0\n\t" 15337 "jc %l[carry]") 15338 : /* Label referred to numerically: "%l2". */ 15339 ("btl %1, %0\n\t" 15340 "jc %l2")); 15341 15342 std::vector<gccjit::block> goto_blocks (@{b_carry@}); 15343 gccjit::extended_asm ext_asm 15344 = (b_start.end_with_extended_asm_goto (asm_template, 15345 goto_blocks, 15346 &b_fallthru) 15347 .add_input_operand ("r", p1) 15348 .add_input_operand ("r", p2) 15349 .add_clobber ("cc")); 15350 @end example 15351 15352 here referencing a @code{gcc_jit_block} named carry. 15353 15354 @code{num_goto_blocks} corresponds to the @code{GotoLabels} parameter within Cs 15355 extended @code{asm} syntax. The block names can be referenced within the 15356 assembler template. 15357 15358 @code{fallthrough_block} can be NULL. If non-NULL, it specifies the block 15359 to fall through to after the statement. 15360 15361 @cartouche 15362 @quotation Note 15363 This is needed since each @ref{18b,,gccjit;;block} must have a 15364 single exit point, as a basic block: you cant jump from the 15365 middle of a block. A goto is implicitly added after the 15366 asm to handle the fallthrough case, which is equivalent to what 15367 would have happened in the C case. 15368 @end quotation 15369 @end cartouche 15370 @end deffn 15371 15372 @geindex gccjit;;extended_asm;;set_volatile_flag (C++ function) 15373 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17set_volatile_flagEb}@anchor{39b}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17set_volatile_flagEb}@anchor{39c}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17set_volatile_flagEb}@anchor{39d}@anchor{cp/topics/asm gccjit extended_asm set_volatile_flag__b}@anchor{39e} 15374 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::set_volatile_flag (bool flag) 15375 15376 Set whether the @ref{38d,,gccjit;;extended_asm} has side-effects, equivalent to the 15377 volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile} 15378 qualifier in Cs extended asm syntax. 15379 15380 For example, to create the equivalent of: 15381 15382 @example 15383 asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX. 15384 "shl $32, %%rdx\n\t" // Shift the upper bits left. 15385 "or %%rdx, %0" // 'Or' in the lower bits. 15386 : "=a" (msr) 15387 : 15388 : "rdx"); 15389 @end example 15390 15391 the following API calls could be used: 15392 15393 @example 15394 gccjit::extended_asm ext_asm 15395 = block.add_extended_asm 15396 ("rdtsc\n\t" /* Returns the time in EDX:EAX. */ 15397 "shl $32, %%rdx\n\t" /* Shift the upper bits left. */ 15398 "or %%rdx, %0") /* 'Or' in the lower bits. */ 15399 .set_volatile_flag (true) 15400 .add_output_operand ("=a", msr) 15401 .add_clobber ("rdx"); 15402 @end example 15403 15404 where the @ref{38d,,gccjit;;extended_asm} is flagged as volatile. 15405 @end deffn 15406 15407 @geindex gccjit;;extended_asm;;set_inline_flag (C++ function) 15408 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm15set_inline_flagEb}@anchor{39f}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm15set_inline_flagEb}@anchor{3a0}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm15set_inline_flagEb}@anchor{3a1}@anchor{cp/topics/asm gccjit extended_asm set_inline_flag__b}@anchor{3a2} 15409 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::set_inline_flag (bool flag) 15410 15411 Set the equivalent of the 15412 inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm} 15413 qualifier in Cs extended @code{asm} syntax. 15414 @end deffn 15415 15416 @geindex gccjit;;extended_asm;;add_output_operand (C++ function) 15417 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{393}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{3a3}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{3a4}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR ssCR gccjit lvalue}@anchor{3a5} 15418 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::add_output_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::lvalue dest) 15419 15420 Add an output operand to the extended @code{asm} statement. See the 15421 Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands} 15422 section of the documentation of the C syntax. 15423 15424 @code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of 15425 Cs extended @code{asm} syntax, and specifies the symbolic name for the operand. 15426 See the overload below for an alternative that does not supply a symbolic 15427 name. 15428 15429 @code{constraint} corresponds to the @code{constraint} component of Cs extended 15430 @code{asm} syntax. 15431 15432 @code{dest} corresponds to the @code{cvariablename} component of Cs extended 15433 @code{asm} syntax. 15434 15435 @example 15436 // Example with a symbolic name ("aIndex"), the equivalent of: 15437 // : [aIndex] "=r" (index) 15438 ext_asm.add_output_operand ("aIndex", "=r", index); 15439 @end example 15440 15441 This function cant be called on an @code{asm goto} as such instructions cant 15442 have outputs; see the 15443 Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels} 15444 section of GCCs Extended Asm documentation. 15445 @end deffn 15446 15447 @geindex gccjit;;extended_asm;;add_output_operand (C++ function) 15448 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{3a6}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{3a7}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{3a8}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR gccjit lvalue}@anchor{3a9} 15449 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::add_output_operand (const std::string &constraint, gccjit::lvalue dest) 15450 15451 As above, but dont supply a symbolic name for the operand. 15452 15453 @example 15454 // Example without a symbolic name, the equivalent of: 15455 // : "=r" (dst) 15456 ext_asm.add_output_operand ("=r", dst); 15457 @end example 15458 @end deffn 15459 15460 @geindex gccjit;;extended_asm;;add_input_operand (C++ function) 15461 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{394}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{3aa}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{3ab}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR ssCR gccjit rvalue}@anchor{3ac} 15462 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::add_input_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::rvalue src) 15463 15464 Add an input operand to the extended @code{asm} statement. See the 15465 Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands} 15466 section of the documentation of the C syntax. 15467 15468 @code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component 15469 of Cs extended @code{asm} syntax. See the overload below for an alternative 15470 that does not supply a symbolic name. 15471 15472 @code{constraint} corresponds to the @code{constraint} component of Cs extended 15473 @code{asm} syntax. 15474 15475 @code{src} corresponds to the @code{cexpression} component of Cs extended 15476 @code{asm} syntax. 15477 15478 @example 15479 // Example with a symbolic name ("aMask"), the equivalent of: 15480 // : [aMask] "r" (Mask) 15481 ext_asm.add_input_operand ("aMask", "r", mask); 15482 @end example 15483 @end deffn 15484 15485 @geindex gccjit;;extended_asm;;add_input_operand (C++ function) 15486 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{3ad}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{3ae}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{3af}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR gccjit rvalue}@anchor{3b0} 15487 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::add_input_operand (const std::string &constraint, gccjit::rvalue src) 15488 15489 As above, but dont supply a symbolic name for the operand. 15490 15491 @example 15492 // Example without a symbolic name, the equivalent of: 15493 // : "r" (src) 15494 ext_asm.add_input_operand ("r", src); 15495 @end example 15496 @end deffn 15497 15498 @geindex gccjit;;extended_asm;;add_clobber (C++ function) 15499 @anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{3b1}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{3b2}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{3b3}@anchor{cp/topics/asm gccjit extended_asm add_clobber__ssCR}@anchor{3b4} 15500 @deffn {C++ Function} gccjit::@ref{38d,,extended_asm} &gccjit::@ref{38d,,extended_asm}::add_clobber (const std::string &victim) 15501 15502 Add @cite{victim} to the list of registers clobbered by the extended @code{asm} 15503 statement. See the 15504 Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#} 15505 section of the documentation of the C syntax. 15506 15507 Statements with multiple clobbers will require multiple calls, one per 15508 clobber. 15509 15510 For example: 15511 15512 @example 15513 ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory"); 15514 @end example 15515 @end deffn 15516 15517 @node Adding top-level assembler statements<2>,,Adding assembler instructions within a function<2>,Using Assembly Language with libgccjit++ 15518 @anchor{cp/topics/asm adding-top-level-assembler-statements}@anchor{3b5} 15519 @subsubsection Adding top-level assembler statements 15520 15521 15522 In addition to creating extended @code{asm} instructions within a function, 15523 there is support for creating top-level assembler statements, outside 15524 of any function. 15525 15526 @geindex gccjit;;context;;add_top_level_asm (C++ function) 15527 @anchor{cp/topics/asm _CPPv4N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{3b6}@anchor{cp/topics/asm _CPPv3N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{3b7}@anchor{cp/topics/asm _CPPv2N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{3b8}@anchor{cp/topics/asm gccjit context add_top_level_asm__cCP gccjit location}@anchor{3b9} 15528 @deffn {C++ Function} void gccjit::@ref{175,,context}::add_top_level_asm (const char *asm_stmts, gccjit::location loc = location()) 15529 15530 Create a set of top-level asm statements, analogous to those created 15531 by GCCs basic @code{asm} syntax in C at file scope. 15532 15533 For example, to create the equivalent of: 15534 15535 @example 15536 asm ("\t.pushsection .text\n" 15537 "\t.globl add_asm\n" 15538 "\t.type add_asm, @@function\n" 15539 "add_asm:\n" 15540 "\tmovq %rdi, %rax\n" 15541 "\tadd %rsi, %rax\n" 15542 "\tret\n" 15543 "\t.popsection\n"); 15544 @end example 15545 15546 the following API calls could be used: 15547 15548 @example 15549 ctxt.add_top_level_asm ("\t.pushsection .text\n" 15550 "\t.globl add_asm\n" 15551 "\t.type add_asm, @@function\n" 15552 "add_asm:\n" 15553 "\tmovq %rdi, %rax\n" 15554 "\tadd %rsi, %rax\n" 15555 "\tret\n" 15556 "\t# some asm here\n" 15557 "\t.popsection\n"); 15558 @end example 15559 @end deffn 15560 15561 @c Copyright (C) 2014-2022 Free Software Foundation, Inc. 15562 @c Originally contributed by David Malcolm <dmalcolm (a] redhat.com> 15563 @c 15564 @c This is free software: you can redistribute it and/or modify it 15565 @c under the terms of the GNU General Public License as published by 15566 @c the Free Software Foundation, either version 3 of the License, or 15567 @c (at your option) any later version. 15568 @c 15569 @c This program is distributed in the hope that it will be useful, but 15570 @c WITHOUT ANY WARRANTY; without even the implied warranty of 15571 @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15572 @c General Public License for more details. 15573 @c 15574 @c You should have received a copy of the GNU General Public License 15575 @c along with this program. If not, see 15576 @c <https://www.gnu.org/licenses/>. 15577 15578 @node Internals,Indices and tables,C++ bindings for libgccjit,Top 15579 @anchor{internals/index doc}@anchor{3ba}@anchor{internals/index internals}@anchor{3bb} 15580 @chapter Internals 15581 15582 15583 @menu 15584 * Working on the JIT library:: 15585 * Running the test suite:: 15586 * Environment variables:: 15587 * Packaging notes:: 15588 * Overview of code structure:: 15589 * Design notes:: 15590 * Submitting patches:: 15591 15592 @end menu 15593 15594 @node Working on the JIT library,Running the test suite,,Internals 15595 @anchor{internals/index working-on-the-jit-library}@anchor{3bc} 15596 @section Working on the JIT library 15597 15598 15599 Having checked out the source code (to src), you can configure and build 15600 the JIT library like this: 15601 15602 @example 15603 mkdir build 15604 mkdir install 15605 PREFIX=$(pwd)/install 15606 cd build 15607 ../src/configure \ 15608 --enable-host-shared \ 15609 --enable-languages=jit,c++ \ 15610 --disable-bootstrap \ 15611 --enable-checking=release \ 15612 --prefix=$PREFIX 15613 nice make -j4 # altering the "4" to however many cores you have 15614 @end example 15615 15616 This should build a libgccjit.so within jit/build/gcc: 15617 15618 @example 15619 [build] $ file gcc/libgccjit.so* 15620 gcc/libgccjit.so: symbolic link to `libgccjit.so.0' 15621 gcc/libgccjit.so.0: symbolic link to `libgccjit.so.0.0.1' 15622 gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped 15623 @end example 15624 15625 Heres what those configuration options mean: 15626 15627 @geindex command line option; --enable-host-shared 15628 @anchor{internals/index cmdoption-enable-host-shared}@anchor{3bd} 15629 @deffn {Option} @w{-}@w{-}enable@w{-}host@w{-}shared 15630 15631 Configuring with this option means that the compiler is built as 15632 position-independent code, which incurs a slight performance hit, 15633 but it necessary for a shared library. 15634 @end deffn 15635 15636 @geindex command line option; --enable-languages=jit@comma{}c++ 15637 @anchor{internals/index cmdoption-enable-languages}@anchor{3be} 15638 @deffn {Option} @w{-}@w{-}enable@w{-}languages=jit,c++ 15639 15640 This specifies which frontends to build. The JIT library looks like 15641 a frontend to the rest of the code. 15642 15643 The C++ portion of the JIT test suite requires the C++ frontend to be 15644 enabled at configure-time, or you may see errors like this when 15645 running the test suite: 15646 15647 @example 15648 xgcc: error: /home/david/jit/src/gcc/testsuite/jit.dg/test-quadratic.cc: C++ compiler not installed on this system 15649 c++: error trying to exec 'cc1plus': execvp: No such file or directory 15650 @end example 15651 @end deffn 15652 15653 @geindex command line option; --disable-bootstrap 15654 @anchor{internals/index cmdoption-disable-bootstrap}@anchor{3bf} 15655 @deffn {Option} @w{-}@w{-}disable@w{-}bootstrap 15656 15657 For hacking on the jit subdirectory, performing a full 15658 bootstrap can be overkill, since its unused by a bootstrap. However, 15659 when submitting patches, you should remove this option, to ensure that 15660 the compiler can still bootstrap itself. 15661 @end deffn 15662 15663 @geindex command line option; --enable-checking=release 15664 @anchor{internals/index cmdoption-enable-checking}@anchor{3c0} 15665 @deffn {Option} @w{-}@w{-}enable@w{-}checking=release 15666 15667 The compile can perform extensive self-checking as it runs, useful when 15668 debugging, but slowing things down. 15669 15670 For maximum speed, configure with @code{--enable-checking=release} to 15671 disable this self-checking. 15672 @end deffn 15673 15674 @node Running the test suite,Environment variables,Working on the JIT library,Internals 15675 @anchor{internals/index running-the-test-suite}@anchor{3c1} 15676 @section Running the test suite 15677 15678 15679 @example 15680 [build] $ cd gcc 15681 [gcc] $ make check-jit RUNTESTFLAGS="-v -v -v" 15682 @end example 15683 15684 A summary of the tests can then be seen in: 15685 15686 @example 15687 jit/build/gcc/testsuite/jit/jit.sum 15688 @end example 15689 15690 and detailed logs in: 15691 15692 @example 15693 jit/build/gcc/testsuite/jit/jit.log 15694 @end example 15695 15696 The test executables are normally deleted after each test is run. For 15697 debugging, they can be preserved by setting 15698 @geindex PRESERVE_EXECUTABLES 15699 @geindex environment variable; PRESERVE_EXECUTABLES 15700 @code{PRESERVE_EXECUTABLES} 15701 in the environment. If so, they can then be seen as: 15702 15703 @example 15704 jit/build/gcc/testsuite/jit/*.exe 15705 @end example 15706 15707 which can be run independently. 15708 15709 You can compile and run individual tests by passing jit.exp=TESTNAME to RUNTESTFLAGS e.g.: 15710 15711 @example 15712 [gcc] $ PRESERVE_EXECUTABLES= \ 15713 make check-jit \ 15714 RUNTESTFLAGS="-v -v -v jit.exp=test-factorial.c" 15715 @end example 15716 15717 and once a test has been compiled, you can debug it directly: 15718 15719 @example 15720 [gcc] $ PATH=.:$PATH \ 15721 LD_LIBRARY_PATH=. \ 15722 LIBRARY_PATH=. \ 15723 gdb --args \ 15724 testsuite/jit/test-factorial.c.exe 15725 @end example 15726 15727 @menu 15728 * Running under valgrind:: 15729 15730 @end menu 15731 15732 @node Running under valgrind,,,Running the test suite 15733 @anchor{internals/index running-under-valgrind}@anchor{3c2} 15734 @subsection Running under valgrind 15735 15736 15737 The jit testsuite detects if 15738 @geindex RUN_UNDER_VALGRIND 15739 @geindex environment variable; RUN_UNDER_VALGRIND 15740 @code{RUN_UNDER_VALGRIND} is present in the 15741 environment (with any value). If it is present, it runs the test client 15742 code under valgrind@footnote{https://valgrind.org}, 15743 specifcally, the default 15744 memcheck@footnote{https://valgrind.org/docs/manual/mc-manual.html} 15745 tool with 15746 --leak-check=full@footnote{https://valgrind.org/docs/manual/mc-manual.html#opt.leak-check}. 15747 15748 It automatically parses the output from valgrind, injecting XFAIL results if 15749 any issues are found, or PASS results if the output is clean. The output 15750 is saved to @code{TESTNAME.exe.valgrind.txt}. 15751 15752 For example, the following invocation verbosely runs the testcase 15753 @code{test-sum-of-squares.c} under valgrind, showing an issue: 15754 15755 @example 15756 $ RUN_UNDER_VALGRIND= \ 15757 make check-jit \ 15758 RUNTESTFLAGS="-v -v -v jit.exp=test-sum-of-squares.c" 15759 15760 (...verbose log contains detailed valgrind errors, if any...) 15761 15762 === jit Summary === 15763 15764 # of expected passes 28 15765 # of expected failures 2 15766 15767 $ less testsuite/jit/jit.sum 15768 (...other results...) 15769 XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: definitely lost: 8 bytes in 1 blocks 15770 XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: unsuppressed errors: 1 15771 (...other results...) 15772 15773 $ less testsuite/jit/test-sum-of-squares.c.exe.valgrind.txt 15774 (...shows full valgrind report for this test case...) 15775 @end example 15776 15777 When running under valgrind, its best to have configured gcc with 15778 @code{--enable-valgrind-annotations}, which automatically suppresses 15779 various known false positives. 15780 15781 @node Environment variables,Packaging notes,Running the test suite,Internals 15782 @anchor{internals/index environment-variables}@anchor{3c3} 15783 @section Environment variables 15784 15785 15786 When running client code against a locally-built libgccjit, three 15787 environment variables need to be set up: 15788 15789 @geindex environment variable; LD_LIBRARY_PATH 15790 @anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{3c4} 15791 @deffn {Environment Variable} LD_LIBRARY_PATH 15792 15793 @quotation 15794 15795 @cite{libgccjit.so} is dynamically linked into client code, so if running 15796 against a locally-built library, @code{LD_LIBRARY_PATH} needs to be set 15797 up appropriately. The library can be found within the gcc 15798 subdirectory of the build tree: 15799 @end quotation 15800 15801 @example 15802 $ file libgccjit.so* 15803 libgccjit.so: symbolic link to `libgccjit.so.0' 15804 libgccjit.so.0: symbolic link to `libgccjit.so.0.0.1' 15805 libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped 15806 @end example 15807 @end deffn 15808 15809 @geindex environment variable; PATH 15810 @anchor{internals/index envvar-PATH}@anchor{3c5} 15811 @deffn {Environment Variable} PATH 15812 15813 The library uses a driver executable for converting from .s assembler 15814 files to .so shared libraries. Specifically, it looks for a name 15815 expanded from 15816 @code{$@{target_noncanonical@}-gcc-$@{gcc_BASEVER@}$@{exeext@}} 15817 such as @code{x86_64-unknown-linux-gnu-gcc-5.0.0}. 15818 15819 Hence @code{PATH} needs to include a directory where the library can 15820 locate this executable. 15821 15822 The executable is normally installed to the installation bindir 15823 (e.g. /usr/bin), but a copy is also created within the gcc 15824 subdirectory of the build tree for running the testsuite, and for ease 15825 of development. 15826 @end deffn 15827 15828 @geindex environment variable; LIBRARY_PATH 15829 @anchor{internals/index envvar-LIBRARY_PATH}@anchor{3c6} 15830 @deffn {Environment Variable} LIBRARY_PATH 15831 15832 The driver executable invokes the linker, and the latter needs to locate 15833 support libraries needed by the generated code, or you will see errors 15834 like: 15835 15836 @example 15837 ld: cannot find crtbeginS.o: No such file or directory 15838 ld: cannot find -lgcc 15839 ld: cannot find -lgcc_s 15840 @end example 15841 15842 Hence if running directly from a locally-built copy (without installing), 15843 @code{LIBRARY_PATH} needs to contain the gcc subdirectory of the build 15844 tree. 15845 @end deffn 15846 15847 For example, to run a binary that uses the library against a non-installed 15848 build of the library in LIBGCCJIT_BUILD_DIR you need an invocation of the 15849 client code like this, to preprend the dir to each of the environment 15850 variables: 15851 15852 @example 15853 $ LD_LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LD_LIBRARY_PATH) \ 15854 PATH=$(LIBGCCJIT_BUILD_DIR):$(PATH) \ 15855 LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LIBRARY_PATH) \ 15856 ./jit-hello-world 15857 hello world 15858 @end example 15859 15860 @node Packaging notes,Overview of code structure,Environment variables,Internals 15861 @anchor{internals/index packaging-notes}@anchor{3c7} 15862 @section Packaging notes 15863 15864 15865 The configure-time option @ref{3bd,,--enable-host-shared} is needed when 15866 building the jit in order to get position-independent code. This will 15867 slow down the regular compiler by a few percent. Hence when packaging gcc 15868 with libgccjit, please configure and build twice: 15869 15870 @quotation 15871 15872 15873 @itemize * 15874 15875 @item 15876 once without @ref{3bd,,--enable-host-shared} for most languages, and 15877 15878 @item 15879 once with @ref{3bd,,--enable-host-shared} for the jit 15880 @end itemize 15881 @end quotation 15882 15883 For example: 15884 15885 @example 15886 # Configure and build with --enable-host-shared 15887 # for the jit: 15888 mkdir configuration-for-jit 15889 pushd configuration-for-jit 15890 $(SRCDIR)/configure \ 15891 --enable-host-shared \ 15892 --enable-languages=jit \ 15893 --prefix=$(DESTDIR) 15894 make 15895 popd 15896 15897 # Configure and build *without* --enable-host-shared 15898 # for maximum speed: 15899 mkdir standard-configuration 15900 pushd standard-configuration 15901 $(SRCDIR)/configure \ 15902 --enable-languages=all \ 15903 --prefix=$(DESTDIR) 15904 make 15905 popd 15906 15907 # Both of the above are configured to install to $(DESTDIR) 15908 # Install the configuration with --enable-host-shared first 15909 # *then* the one without, so that the faster build 15910 # of "cc1" et al overwrites the slower build. 15911 pushd configuration-for-jit 15912 make install 15913 popd 15914 15915 pushd standard-configuration 15916 make install 15917 popd 15918 @end example 15919 15920 @node Overview of code structure,Design notes,Packaging notes,Internals 15921 @anchor{internals/index overview-of-code-structure}@anchor{3c8} 15922 @section Overview of code structure 15923 15924 15925 The library is implemented in C++. The source files have the @code{.c} 15926 extension for legacy reasons. 15927 15928 15929 @itemize * 15930 15931 @item 15932 @code{libgccjit.cc} implements the API entrypoints. It performs error 15933 checking, then calls into classes of the gcc::jit::recording namespace 15934 within @code{jit-recording.cc} and @code{jit-recording.h}. 15935 15936 @item 15937 The gcc::jit::recording classes (within @code{jit-recording.cc} and 15938 @code{jit-recording.h}) record the API calls that are made: 15939 15940 @quotation 15941 15942 @example 15943 15944 /* Indentation indicates inheritance: */ 15945 class context; 15946 class memento; 15947 class string; 15948 class location; 15949 class type; 15950 class function_type; 15951 class compound_type; 15952 class struct_; 15953 class union_; 15954 class vector_type; 15955 class field; 15956 class bitfield; 15957 class fields; 15958 class function; 15959 class block; 15960 class rvalue; 15961 class lvalue; 15962 class local; 15963 class global; 15964 class param; 15965 class base_call; 15966 class function_pointer; 15967 class statement; 15968 class extended_asm; 15969 class case_; 15970 class top_level_asm; 15971 15972 @end example 15973 @end quotation 15974 15975 @item 15976 When the context is compiled, the gcc::jit::playback classes (within 15977 @code{jit-playback.cc} and @code{jit-playback.h}) replay the API calls 15978 within langhook:parse_file: 15979 15980 @quotation 15981 15982 @example 15983 15984 /* Indentation indicates inheritance: */ 15985 class context; 15986 class wrapper; 15987 class type; 15988 class compound_type; 15989 class field; 15990 class function; 15991 class block; 15992 class rvalue; 15993 class lvalue; 15994 class param; 15995 class source_file; 15996 class source_line; 15997 class location; 15998 class case_; 15999 16000 @end example 16001 16002 @example 16003 Client Code . Generated . libgccjit.so 16004 . code . 16005 . . JIT API . JIT "Frontend". (libbackend.a) 16006 .................................................................................... 16007 . . . . 16008 > . . 16009 . . . . 16010 . . V . . 16011 . . > libgccjit.cc . 16012 . . (error-checking). 16013 . . . 16014 . . > jit-recording.cc 16015 . . (record API calls) 16016 . . < . 16017 . . . . 16018 < . . 16019 . . . . 16020 . . . . 16021 V . . gcc_jit_context_compile . 16022 > . . 16023 . . start of recording::context::compile () 16024 . . . . 16025 . . start of playback::context::compile () 16026 . . (create tempdir) . 16027 . . . . 16028 . . ACQUIRE MUTEX . 16029 . . . . 16030 . . V> toplev::main (for now) 16031 . . . . 16032 . . . . (various code) 16033 . . . . 16034 . . . . V 16035 . . . < langhook:parse_file 16036 . . . . 16037 . . . (jit_langhook_parse_file) 16038 . . . . 16039 ............................................................VVVVVVVVVVVVV... 16040 . . . . No GC in here 16041 . . . jit-playback.cc 16042 . . . (playback of API calls) 16043 . . . > creation of functions, 16044 . . . . types, expression trees 16045 . . . < etc 16046 . . . (handle_locations: add locations to 16047 . . . linemap and associate them with trees) 16048 . . . . 16049 . . . . No GC in here 16050 ............................................................AAAAAAAAAAAAA... 16051 . . . for each function 16052 . . . > postprocess 16053 . . . . 16054 . . . > cgraph_finalize_function 16055 . . . < 16056 . . . < . 16057 . . . . 16058 . . . > (end of 16059 . . . . langhook_parse_file) 16060 . . . . 16061 . . . . (various code) 16062 . . . . 16063 . . . . 16064 . . . < langhook:write_globals 16065 . . . . 16066 . . . (jit_langhook_write_globals) 16067 . . . . 16068 . . . . 16069 . . . > finalize_compilation_unit 16070 . . . . 16071 . . . . (the middleend and backend) 16072 . . . . 16073 . . < end of toplev::main 16074 . . . . 16075 . . V> toplev::finalize 16076 . . . . (purge internal state) 16077 . . < end of toplev::finalize 16078 . . . . 16079 . . V> playback::context::postprocess: 16080 . . . . 16081 . . (assuming an in-memory compile): 16082 . . . . 16083 . . --> Convert assembler to DSO, via embedded 16084 . . copy of driver: 16085 . . driver::main () 16086 . . invocation of "as" 16087 . . invocation of "ld" 16088 . . driver::finalize () 16089 . . <---- 16090 . . . . 16091 . . . Load DSO (dlopen "fake.so") 16092 . . . . 16093 . . . Bundle it up in a jit::result 16094 . . < . . 16095 . . . . 16096 . . RELEASE MUTEX . 16097 . . . . 16098 . . end of playback::context::compile () 16099 . . . . 16100 . . playback::context dtor 16101 . . > . . 16102 . . Normally we cleanup the tempdir here: 16103 . . ("fake.so" is unlinked from the 16104 . . filesystem at this point) 16105 . . If the client code requested debuginfo, the 16106 . . cleanup happens later (in gcc_jit_result_release) 16107 . . to make it easier on the debugger (see PR jit/64206) 16108 . . < . . 16109 . . . . 16110 . . end of recording::context::compile () 16111 < . . 16112 . . . . 16113 V . . gcc_jit_result_get_code . 16114 > . . 16115 . . dlsym () within loaded DSO 16116 < . . 16117 Get (void*). . . . 16118 . . . . 16119 Call it . . . . 16120 > . . . 16121 . . . . 16122 . . . . 16123 < . . . 16124 . . . . 16125 etc . . . . 16126 . . . . 16127 V . . gcc_jit_result_release . 16128 > . . 16129 . . dlclose () the loaded DSO 16130 . . (code becomes uncallable) 16131 . . . . 16132 . . If the client code requested debuginfo, then 16133 . . cleanup of the tempdir was delayed. 16134 . . If that was the case, clean it up now. 16135 < . . 16136 . . . . 16137 @end example 16138 @end quotation 16139 @end itemize 16140 16141 Here is a high-level summary from @code{jit-common.h}: 16142 16143 @quotation 16144 16145 In order to allow jit objects to be usable outside of a compile 16146 whilst working with the existing structure of GCCs code the 16147 C API is implemented in terms of a gcc::jit::recording::context, 16148 which records the calls made to it. 16149 16150 When a gcc_jit_context is compiled, the recording context creates a 16151 playback context. The playback context invokes the bulk of the GCC 16152 code, and within the frontend parsing hook, plays back the recorded 16153 API calls, creating GCC tree objects. 16154 16155 So there are two parallel families of classes: those relating to 16156 recording, and those relating to playback: 16157 16158 16159 @itemize * 16160 16161 @item 16162 Visibility: recording objects are exposed back to client code, 16163 whereas playback objects are internal to the library. 16164 16165 @item 16166 Lifetime: recording objects have a lifetime equal to that of the 16167 recording context that created them, whereas playback objects only 16168 exist within the frontend hook. 16169 16170 @item 16171 Memory allocation: recording objects are allocated by the recording 16172 context, and automatically freed by it when the context is released, 16173 whereas playback objects are allocated within the GC heap, and 16174 garbage-collected; they can own GC-references. 16175 16176 @item 16177 Integration with rest of GCC: recording objects are unrelated to the 16178 rest of GCC, whereas playback objects are wrappers around tree 16179 instances. Hence you cant ask a recording rvalue or lvalue what its 16180 type is, whereas you can for a playback rvalue of lvalue (since it 16181 can work with the underlying GCC tree nodes). 16182 16183 @item 16184 Instancing: There can be multiple recording contexts alive at once 16185 (albeit it only one compiling at once), whereas there can only be one 16186 playback context alive at one time (since it interacts with the GC). 16187 @end itemize 16188 16189 Ultimately if GCC could support multiple GC heaps and contexts, and 16190 finer-grained initialization, then this recording vs playback 16191 distinction could be eliminated. 16192 16193 During a playback, we associate objects from the recording with 16194 their counterparts during this playback. For simplicity, we store this 16195 within the recording objects, as @code{void *m_playback_obj}, casting it to 16196 the appropriate playback object subclass. For these casts to make 16197 sense, the two class hierarchies need to have the same structure. 16198 16199 Note that the playback objects that @code{m_playback_obj} points to are 16200 GC-allocated, but the recording objects dont own references: 16201 these associations only exist within a part of the code where 16202 the GC doesnt collect, and are set back to NULL before the GC can 16203 run. 16204 @end quotation 16205 @anchor{internals/index example-of-log-file}@anchor{5c} 16206 Another way to understand the structure of the code is to enable logging, 16207 via @ref{5b,,gcc_jit_context_set_logfile()}. Here is an example of a log 16208 generated via this call: 16209 16210 @example 16211 JIT: libgccjit (GCC) version 6.0.0 20150803 (experimental) (x86_64-pc-linux-gnu) 16212 JIT: compiled by GNU C version 4.8.3 20140911 (Red Hat 4.8.3-7), GMP version 5.1.2, MPFR version 3.1.2, MPC version 1.0.1 16213 JIT: entering: gcc_jit_context_set_str_option 16214 JIT: GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe" 16215 JIT: exiting: gcc_jit_context_set_str_option 16216 JIT: entering: gcc_jit_context_set_int_option 16217 JIT: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3 16218 JIT: exiting: gcc_jit_context_set_int_option 16219 JIT: entering: gcc_jit_context_set_bool_option 16220 JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO: true 16221 JIT: exiting: gcc_jit_context_set_bool_option 16222 JIT: entering: gcc_jit_context_set_bool_option 16223 JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false 16224 JIT: exiting: gcc_jit_context_set_bool_option 16225 JIT: entering: gcc_jit_context_set_bool_option 16226 JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false 16227 JIT: exiting: gcc_jit_context_set_bool_option 16228 JIT: entering: gcc_jit_context_set_bool_option 16229 JIT: GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true 16230 JIT: exiting: gcc_jit_context_set_bool_option 16231 JIT: entering: gcc_jit_context_set_bool_option 16232 JIT: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false 16233 JIT: exiting: gcc_jit_context_set_bool_option 16234 JIT: entering: gcc_jit_context_get_type 16235 JIT: exiting: gcc_jit_context_get_type 16236 JIT: entering: gcc_jit_context_get_type 16237 JIT: exiting: gcc_jit_context_get_type 16238 JIT: entering: gcc_jit_context_new_param 16239 JIT: exiting: gcc_jit_context_new_param 16240 JIT: entering: gcc_jit_context_new_function 16241 JIT: exiting: gcc_jit_context_new_function 16242 JIT: entering: gcc_jit_context_new_param 16243 JIT: exiting: gcc_jit_context_new_param 16244 JIT: entering: gcc_jit_context_get_type 16245 JIT: exiting: gcc_jit_context_get_type 16246 JIT: entering: gcc_jit_context_new_function 16247 JIT: exiting: gcc_jit_context_new_function 16248 JIT: entering: gcc_jit_context_new_string_literal 16249 JIT: exiting: gcc_jit_context_new_string_literal 16250 JIT: entering: gcc_jit_function_new_block 16251 JIT: exiting: gcc_jit_function_new_block 16252 JIT: entering: gcc_jit_block_add_comment 16253 JIT: exiting: gcc_jit_block_add_comment 16254 JIT: entering: gcc_jit_context_new_call 16255 JIT: exiting: gcc_jit_context_new_call 16256 JIT: entering: gcc_jit_block_add_eval 16257 JIT: exiting: gcc_jit_block_add_eval 16258 JIT: entering: gcc_jit_block_end_with_void_return 16259 JIT: exiting: gcc_jit_block_end_with_void_return 16260 JIT: entering: gcc_jit_context_dump_reproducer_to_file 16261 JIT: entering: void gcc::jit::recording::context::dump_reproducer_to_file(const char*) 16262 JIT: exiting: void gcc::jit::recording::context::dump_reproducer_to_file(const char*) 16263 JIT: exiting: gcc_jit_context_dump_reproducer_to_file 16264 JIT: entering: gcc_jit_context_compile 16265 JIT: in-memory compile of ctxt: 0x1283e20 16266 JIT: entering: gcc::jit::result* gcc::jit::recording::context::compile() 16267 JIT: GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe" 16268 JIT: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3 16269 JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO: true 16270 JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false 16271 JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false 16272 JIT: GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE: false 16273 JIT: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false 16274 JIT: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING: false 16275 JIT: GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true 16276 JIT: GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: false 16277 JIT: gcc_jit_context_set_bool_allow_unreachable_blocks: false 16278 JIT: gcc_jit_context_set_bool_use_external_driver: false 16279 JIT: entering: void gcc::jit::recording::context::validate() 16280 JIT: exiting: void gcc::jit::recording::context::validate() 16281 JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*) 16282 JIT: exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*) 16283 JIT: entering: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*) 16284 JIT: exiting: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*) 16285 JIT: entering: void gcc::jit::playback::context::compile() 16286 JIT: entering: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int) 16287 JIT: exiting: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int) 16288 JIT: entering: bool gcc::jit::tempdir::create() 16289 JIT: m_path_template: /tmp/libgccjit-XXXXXX 16290 JIT: m_path_tempdir: /tmp/libgccjit-CKq1M9 16291 JIT: exiting: bool gcc::jit::tempdir::create() 16292 JIT: entering: void gcc::jit::playback::context::acquire_mutex() 16293 JIT: exiting: void gcc::jit::playback::context::acquire_mutex() 16294 JIT: entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*) 16295 JIT: reusing cached configure-time options 16296 JIT: configure_time_options[0]: -mtune=generic 16297 JIT: configure_time_options[1]: -march=x86-64 16298 JIT: exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*) 16299 JIT: entering: toplev::main 16300 JIT: argv[0]: ./test-hello-world.c.exe 16301 JIT: argv[1]: /tmp/libgccjit-CKq1M9/fake.c 16302 JIT: argv[2]: -fPIC 16303 JIT: argv[3]: -O3 16304 JIT: argv[4]: -g 16305 JIT: argv[5]: -quiet 16306 JIT: argv[6]: --param 16307 JIT: argv[7]: ggc-min-expand=0 16308 JIT: argv[8]: --param 16309 JIT: argv[9]: ggc-min-heapsize=0 16310 JIT: argv[10]: -mtune=generic 16311 JIT: argv[11]: -march=x86-64 16312 JIT: entering: bool jit_langhook_init() 16313 JIT: exiting: bool jit_langhook_init() 16314 JIT: entering: void gcc::jit::playback::context::replay() 16315 JIT: entering: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*) 16316 JIT: exiting: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*) 16317 JIT: entering: void gcc::jit::recording::context::disassociate_from_playback() 16318 JIT: exiting: void gcc::jit::recording::context::disassociate_from_playback() 16319 JIT: entering: void gcc::jit::playback::context::handle_locations() 16320 JIT: exiting: void gcc::jit::playback::context::handle_locations() 16321 JIT: entering: void gcc::jit::playback::function::build_stmt_list() 16322 JIT: exiting: void gcc::jit::playback::function::build_stmt_list() 16323 JIT: entering: void gcc::jit::playback::function::build_stmt_list() 16324 JIT: exiting: void gcc::jit::playback::function::build_stmt_list() 16325 JIT: entering: void gcc::jit::playback::function::postprocess() 16326 JIT: exiting: void gcc::jit::playback::function::postprocess() 16327 JIT: entering: void gcc::jit::playback::function::postprocess() 16328 JIT: exiting: void gcc::jit::playback::function::postprocess() 16329 JIT: exiting: void gcc::jit::playback::context::replay() 16330 JIT: exiting: toplev::main 16331 JIT: entering: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*) 16332 JIT: exiting: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*) 16333 JIT: entering: toplev::finalize 16334 JIT: exiting: toplev::finalize 16335 JIT: entering: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) 16336 JIT: entering: void gcc::jit::playback::context::convert_to_dso(const char*) 16337 JIT: entering: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) 16338 JIT: entering: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*) 16339 JIT: exiting: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*) 16340 JIT: argv[0]: x86_64-unknown-linux-gnu-gcc-6.0.0 16341 JIT: argv[1]: -m64 16342 JIT: argv[2]: -shared 16343 JIT: argv[3]: /tmp/libgccjit-CKq1M9/fake.s 16344 JIT: argv[4]: -o 16345 JIT: argv[5]: /tmp/libgccjit-CKq1M9/fake.so 16346 JIT: argv[6]: -fno-use-linker-plugin 16347 JIT: entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) 16348 JIT: exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) 16349 JIT: exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) 16350 JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*) 16351 JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso() 16352 JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO was set: handing over tempdir to jit::result 16353 JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*) 16354 JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*) 16355 JIT: exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso() 16356 JIT: exiting: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) 16357 JIT: entering: void gcc::jit::playback::context::release_mutex() 16358 JIT: exiting: void gcc::jit::playback::context::release_mutex() 16359 JIT: exiting: void gcc::jit::playback::context::compile() 16360 JIT: entering: gcc::jit::playback::context::~context() 16361 JIT: exiting: gcc::jit::playback::context::~context() 16362 JIT: exiting: gcc::jit::result* gcc::jit::recording::context::compile() 16363 JIT: gcc_jit_context_compile: returning (gcc_jit_result *)0x12f75d0 16364 JIT: exiting: gcc_jit_context_compile 16365 JIT: entering: gcc_jit_result_get_code 16366 JIT: locating fnname: hello_world 16367 JIT: entering: void* gcc::jit::result::get_code(const char*) 16368 JIT: exiting: void* gcc::jit::result::get_code(const char*) 16369 JIT: gcc_jit_result_get_code: returning (void *)0x7ff6b8cd87f0 16370 JIT: exiting: gcc_jit_result_get_code 16371 JIT: entering: gcc_jit_context_release 16372 JIT: deleting ctxt: 0x1283e20 16373 JIT: entering: gcc::jit::recording::context::~context() 16374 JIT: exiting: gcc::jit::recording::context::~context() 16375 JIT: exiting: gcc_jit_context_release 16376 JIT: entering: gcc_jit_result_release 16377 JIT: deleting result: 0x12f75d0 16378 JIT: entering: virtual gcc::jit::result::~result() 16379 JIT: entering: gcc::jit::tempdir::~tempdir() 16380 JIT: unlinking .s file: /tmp/libgccjit-CKq1M9/fake.s 16381 JIT: unlinking .so file: /tmp/libgccjit-CKq1M9/fake.so 16382 JIT: removing tempdir: /tmp/libgccjit-CKq1M9 16383 JIT: exiting: gcc::jit::tempdir::~tempdir() 16384 JIT: exiting: virtual gcc::jit::result::~result() 16385 JIT: exiting: gcc_jit_result_release 16386 JIT: gcc::jit::logger::~logger() 16387 @end example 16388 16389 @node Design notes,Submitting patches,Overview of code structure,Internals 16390 @anchor{internals/index design-notes}@anchor{3c9} 16391 @section Design notes 16392 16393 16394 It should not be possible for client code to cause an internal compiler 16395 error. If this @emph{does} happen, the root cause should be isolated (perhaps 16396 using @ref{5d,,gcc_jit_context_dump_reproducer_to_file()}) and the cause 16397 should be rejected via additional checking. The checking ideally should 16398 be within the libgccjit API entrypoints in libgccjit.cc, since this is as 16399 close as possible to the error; failing that, a good place is within 16400 @code{recording::context::validate ()} in jit-recording.cc. 16401 16402 @node Submitting patches,,Design notes,Internals 16403 @anchor{internals/index submitting-patches}@anchor{3ca} 16404 @section Submitting patches 16405 16406 16407 Please read the contribution guidelines for gcc at 16408 @indicateurl{https://gcc.gnu.org/contribute.html}. 16409 16410 Patches for the jit should be sent to both the 16411 @email{gcc-patches@@gcc.gnu.org} and @email{jit@@gcc.gnu.org} mailing lists, 16412 with jit and PATCH in the Subject line. 16413 16414 You dont need to do a full bootstrap for code that just touches the 16415 @code{jit} and @code{testsuite/jit.dg} subdirectories. However, please run 16416 @code{make check-jit} before submitting the patch, and mention the results 16417 in your email (along with the host triple that the tests were run on). 16418 16419 A good patch should contain the information listed in the 16420 gcc contribution guide linked to above; for a @code{jit} patch, the patch 16421 shold contain: 16422 16423 @quotation 16424 16425 16426 @itemize * 16427 16428 @item 16429 the code itself (for example, a new API entrypoint will typically 16430 touch @code{libgccjit.h} and @code{.c}, along with support code in 16431 @code{jit-recording.[ch]} and @code{jit-playback.[ch]} as appropriate) 16432 16433 @item 16434 test coverage 16435 16436 @item 16437 documentation for the C API 16438 16439 @item 16440 documentation for the C++ API 16441 @end itemize 16442 @end quotation 16443 16444 A patch that adds new API entrypoints should also contain: 16445 16446 @quotation 16447 16448 16449 @itemize * 16450 16451 @item 16452 a feature macro in @code{libgccjit.h} so that client code that doesnt 16453 use a configure mechanism can still easily detect the presence of 16454 the entrypoint. See e.g. @code{LIBGCCJIT_HAVE_SWITCH_STATEMENTS} (for 16455 a category of entrypoints) and 16456 @code{LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks} 16457 (for an individual entrypoint). 16458 16459 @item 16460 a new ABI tag containing the new symbols (in @code{libgccjit.map}), so 16461 that we can detect client code that uses them 16462 16463 @item 16464 Support for @ref{5d,,gcc_jit_context_dump_reproducer_to_file()}. Most 16465 jit testcases attempt to dump their contexts to a .c file; @code{jit.exp} 16466 then sanity-checks the generated c by compiling them (though 16467 not running them). A new API entrypoint 16468 needs to know how to write itself back out to C (by implementing 16469 @code{gcc::jit::recording::memento::write_reproducer} for the appropriate 16470 @code{memento} subclass). 16471 16472 @item 16473 C++ bindings for the new entrypoints (see @code{libgccjit++.h}); ideally 16474 with test coverage, though the C++ API test coverage is admittedly 16475 spotty at the moment 16476 16477 @item 16478 documentation for the new C entrypoints 16479 16480 @item 16481 documentation for the new C++ entrypoints 16482 16483 @item 16484 documentation for the new ABI tag (see @code{topics/compatibility.rst}). 16485 @end itemize 16486 @end quotation 16487 16488 Depending on the patch you can either extend an existing test case, or 16489 add a new test case. If you add an entirely new testcase: @code{jit.exp} 16490 expects jit testcases to begin with @code{test-}, or @code{test-error-} (for a 16491 testcase that generates an error on a @ref{8,,gcc_jit_context}). 16492 16493 Every new testcase that doesnt generate errors should also touch 16494 @code{gcc/testsuite/jit.dg/all-non-failing-tests.h}: 16495 16496 @quotation 16497 16498 16499 @itemize * 16500 16501 @item 16502 Testcases that dont generate errors should ideally be added to the 16503 @code{testcases} array in that file; this means that, in addition 16504 to being run standalone, they also get run within 16505 @code{test-combination.c} (which runs all successful tests inside one 16506 big @ref{8,,gcc_jit_context}), and @code{test-threads.c} (which runs all 16507 successful tests in one process, each one running in a different 16508 thread on a different @ref{8,,gcc_jit_context}). 16509 16510 @cartouche 16511 @quotation Note 16512 Given that exported functions within a @ref{8,,gcc_jit_context} 16513 must have unique names, and most testcases are run within 16514 @code{test-combination.c}, this means that every jit-compiled test 16515 function typically needs a name thats unique across the entire 16516 test suite. 16517 @end quotation 16518 @end cartouche 16519 16520 @item 16521 Testcases that arent to be added to the @code{testcases} array should 16522 instead add a comment to the file clarifying why theyre not in that 16523 array. See the file for examples. 16524 @end itemize 16525 @end quotation 16526 16527 Typically a patch that touches the .rst documentation will also need the 16528 texinfo to be regenerated. You can do this with 16529 Sphinx 1.0@footnote{https://sphinx-doc.org/} or later by 16530 running @code{make texinfo} within @code{SRCDIR/gcc/jit/docs}. Dont do this 16531 within the patch sent to the mailing list; it can often be relatively 16532 large and inconsequential (e.g. anchor renumbering), rather like generated 16533 configure changes from configure.ac. You can regenerate it when 16534 committing to svn. 16535 16536 @node Indices and tables,Index,Internals,Top 16537 @anchor{index indices-and-tables}@anchor{3cb} 16538 @unnumbered Indices and tables 16539 16540 16541 16542 @itemize * 16543 16544 @item 16545 genindex 16546 16547 @item 16548 modindex 16549 16550 @item 16551 search 16552 @end itemize 16553 16554 @c Some notes: 16555 @c 16556 @c The Sphinx C domain appears to lack explicit support for enum values, 16557 @c so I've been using :c:macro: for them. 16558 @c 16559 @c See https://sphinx-doc.org/domains.html#the-c-domain 16560 16561 @node Index,,Indices and tables,Top 16562 @unnumbered Index 16563 16564 16565 @printindex ge 16566 16567 16568 @c %**end of body 16569 @bye 16570