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 24libgccjit 11.0.0 (experimental 20210114), Jan 14, 2021 25 26David Malcolm 27 28Copyright @copyright{} 2014-2021 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-2021 Free Software Foundation, Inc. 52@c Originally contributed by David Malcolm <dmalcolm@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 <http://www.gnu.org/licenses/>. 67 68This document describes libgccjit@footnote{http://gcc.gnu.org/wiki/JIT}, an API 69for embedding GCC inside programs and libraries. 70 71There are actually two APIs for the library: 72 73 74@itemize * 75 76@item 77a pure C API: @code{libgccjit.h} 78 79@item 80a C++ wrapper API: @code{libgccjit++.h}. This is a collection of “thin” 81wrapper classes around the C API, to save typing. 82@end itemize 83 84Contents: 85 86@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 87@c Originally contributed by David Malcolm <dmalcolm@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 <http://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 114Tutorial 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 122Tutorial part 2: Creating a trivial machine code function 123 124* Error-handling:: 125* Options:: 126* Full example:: 127 128Tutorial 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 135Tutorial 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 148Behind the curtain: How does our code get optimized? 149 150* Optimizing away stack manipulation:: 151* Elimination of tail recursion:: 152 153Tutorial 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 160Topic 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 174Compilation contexts 175 176* Lifetime-management:: 177* Thread-safety:: 178* Error-handling: Error-handling<2>. 179* Debugging:: 180* Options: Options<2>. 181 182Options 183 184* String Options:: 185* Boolean options:: 186* Integer options:: 187* Additional command-line options:: 188 189Types 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 197Expressions 198 199* Rvalues:: 200* Lvalues:: 201* Working with pointers@comma{} structs and unions: Working with pointers structs and unions. 202 203Rvalues 204 205* Simple expressions:: 206* Vector expressions:: 207* Unary Operations:: 208* Binary Operations:: 209* Comparisons:: 210* Function calls:: 211* Function pointers:: 212* Type-coercion:: 213 214Lvalues 215 216* Global variables:: 217 218Creating and using functions 219 220* Params:: 221* Functions:: 222* Blocks:: 223* Statements:: 224 225Source Locations 226 227* Faking it:: 228 229Compiling a context 230 231* In-memory compilation:: 232* Ahead-of-time compilation:: 233 234ABI and API compatibility 235 236* Programmatically checking version:: 237* ABI symbol tags:: 238 239ABI symbol tags 240 241* LIBGCCJIT_ABI_0:: 242* LIBGCCJIT_ABI_1:: 243* LIBGCCJIT_ABI_2:: 244* LIBGCCJIT_ABI_3:: 245* LIBGCCJIT_ABI_4:: 246* LIBGCCJIT_ABI_5:: 247* LIBGCCJIT_ABI_6:: 248* LIBGCCJIT_ABI_7:: 249* LIBGCCJIT_ABI_8:: 250* LIBGCCJIT_ABI_9:: 251* LIBGCCJIT_ABI_10:: 252* LIBGCCJIT_ABI_11:: 253* LIBGCCJIT_ABI_12:: 254* LIBGCCJIT_ABI_13:: 255* LIBGCCJIT_ABI_14:: 256* LIBGCCJIT_ABI_15:: 257 258Performance 259 260* The timing API:: 261 262Using Assembly Language with libgccjit 263 264* Adding assembler instructions within a function:: 265* Adding top-level assembler statements:: 266 267C++ bindings for libgccjit 268 269* Tutorial: Tutorial<2>. 270* Topic Reference: Topic Reference<2>. 271 272Tutorial 273 274* Tutorial part 1; “Hello world”: Tutorial part 1 “Hello world”<2>. 275* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>. 276* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>. 277* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>. 278 279Tutorial part 2: Creating a trivial machine code function 280 281* Options: Options<3>. 282* Full example: Full example<3>. 283 284Tutorial part 3: Loops and variables 285 286* Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>. 287* Control flow: Control flow<2>. 288* Visualizing the control flow graph: Visualizing the control flow graph<2>. 289* Full example: Full example<4>. 290 291Tutorial part 4: Adding JIT-compilation to a toy interpreter 292 293* Our toy interpreter: Our toy interpreter<2>. 294* Compiling to machine code: Compiling to machine code<2>. 295* Setting things up: Setting things up<2>. 296* Populating the function: Populating the function<2>. 297* Verifying the control flow graph: Verifying the control flow graph<2>. 298* Compiling the context: Compiling the context<2>. 299* Single-stepping through the generated code: Single-stepping through the generated code<2>. 300* Examining the generated code: Examining the generated code<2>. 301* Putting it all together: Putting it all together<2>. 302* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>. 303 304Behind the curtain: How does our code get optimized? 305 306* Optimizing away stack manipulation: Optimizing away stack manipulation<2>. 307* Elimination of tail recursion: Elimination of tail recursion<2>. 308 309Topic Reference 310 311* Compilation contexts: Compilation contexts<2>. 312* Objects: Objects<2>. 313* Types: Types<2>. 314* Expressions: Expressions<2>. 315* Creating and using functions: Creating and using functions<2>. 316* Source Locations: Source Locations<2>. 317* Compiling a context: Compiling a context<2>. 318* Using Assembly Language with libgccjit++:: 319 320Compilation contexts 321 322* Lifetime-management: Lifetime-management<2>. 323* Thread-safety: Thread-safety<2>. 324* Error-handling: Error-handling<3>. 325* Debugging: Debugging<2>. 326* Options: Options<4>. 327 328Options 329 330* String Options: String Options<2>. 331* Boolean options: Boolean options<2>. 332* Integer options: Integer options<2>. 333* Additional command-line options: Additional command-line options<2>. 334 335Types 336 337* Standard types: Standard types<2>. 338* Pointers@comma{} const@comma{} and volatile: Pointers const and volatile<2>. 339* Vector types: Vector types<2>. 340* Structures and unions: Structures and unions<2>. 341 342Expressions 343 344* Rvalues: Rvalues<2>. 345* Lvalues: Lvalues<2>. 346* Working with pointers@comma{} structs and unions: Working with pointers structs and unions<2>. 347 348Rvalues 349 350* Simple expressions: Simple expressions<2>. 351* Vector expressions: Vector expressions<2>. 352* Unary Operations: Unary Operations<2>. 353* Binary Operations: Binary Operations<2>. 354* Comparisons: Comparisons<2>. 355* Function calls: Function calls<2>. 356* Function pointers: Function pointers<3>. 357* Type-coercion: Type-coercion<2>. 358 359Lvalues 360 361* Global variables: Global variables<2>. 362 363Creating and using functions 364 365* Params: Params<2>. 366* Functions: Functions<2>. 367* Blocks: Blocks<2>. 368* Statements: Statements<2>. 369 370Source Locations 371 372* Faking it: Faking it<2>. 373 374Compiling a context 375 376* In-memory compilation: In-memory compilation<2>. 377* Ahead-of-time compilation: Ahead-of-time compilation<2>. 378 379Using Assembly Language with libgccjit++ 380 381* Adding assembler instructions within a function: Adding assembler instructions within a function<2>. 382* Adding top-level assembler statements: Adding top-level assembler statements<2>. 383 384Internals 385 386* Working on the JIT library:: 387* Running the test suite:: 388* Environment variables:: 389* Packaging notes:: 390* Overview of code structure:: 391* Design notes:: 392* Submitting patches:: 393 394Running the test suite 395 396* Running under valgrind:: 397 398@end detailmenu 399@end menu 400 401@node Tutorial,Topic Reference,Top,Top 402@anchor{intro/index doc}@anchor{1}@anchor{intro/index libgccjit}@anchor{2}@anchor{intro/index tutorial}@anchor{3} 403@chapter Tutorial 404 405 406@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 407@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 408@c 409@c This is free software: you can redistribute it and/or modify it 410@c under the terms of the GNU General Public License as published by 411@c the Free Software Foundation, either version 3 of the License, or 412@c (at your option) any later version. 413@c 414@c This program is distributed in the hope that it will be useful, but 415@c WITHOUT ANY WARRANTY; without even the implied warranty of 416@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 417@c General Public License for more details. 418@c 419@c You should have received a copy of the GNU General Public License 420@c along with this program. If not, see 421@c <http://www.gnu.org/licenses/>. 422 423@menu 424* Tutorial part 1; “Hello world”: Tutorial part 1 “Hello world”. 425* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function. 426* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables. 427* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter. 428* Tutorial part 5; Implementing an Ahead-of-Time compiler: Tutorial part 5 Implementing an Ahead-of-Time compiler. 429 430@end menu 431 432@node Tutorial part 1 “Hello world”,Tutorial part 2 Creating a trivial machine code function,,Tutorial 433@anchor{intro/tutorial01 doc}@anchor{4}@anchor{intro/tutorial01 tutorial-part-1-hello-world}@anchor{5} 434@section Tutorial part 1: “Hello world” 435 436 437Before we look at the details of the API, let’s look at building and 438running programs that use the library. 439 440Here’s a toy “hello world” program that uses the library to synthesize 441a call to @cite{printf} and uses it to write a message to stdout. 442 443Don’t worry about the content of the program for now; we’ll cover 444the details in later parts of this tutorial. 445 446@quotation 447 448@example 449/* Smoketest example for libgccjit.so 450 Copyright (C) 2014-2021 Free Software Foundation, Inc. 451 452This file is part of GCC. 453 454GCC is free software; you can redistribute it and/or modify it 455under the terms of the GNU General Public License as published by 456the Free Software Foundation; either version 3, or (at your option) 457any later version. 458 459GCC is distributed in the hope that it will be useful, but 460WITHOUT ANY WARRANTY; without even the implied warranty of 461MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 462General Public License for more details. 463 464You should have received a copy of the GNU General Public License 465along with GCC; see the file COPYING3. If not see 466<http://www.gnu.org/licenses/>. */ 467 468#include <libgccjit.h> 469 470#include <stdlib.h> 471#include <stdio.h> 472 473static void 474create_code (gcc_jit_context *ctxt) 475@{ 476 /* Let's try to inject the equivalent of: 477 void 478 greet (const char *name) 479 @{ 480 printf ("hello %s\n", name); 481 @} 482 */ 483 gcc_jit_type *void_type = 484 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); 485 gcc_jit_type *const_char_ptr_type = 486 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR); 487 gcc_jit_param *param_name = 488 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name"); 489 gcc_jit_function *func = 490 gcc_jit_context_new_function (ctxt, NULL, 491 GCC_JIT_FUNCTION_EXPORTED, 492 void_type, 493 "greet", 494 1, ¶m_name, 495 0); 496 497 gcc_jit_param *param_format = 498 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format"); 499 gcc_jit_function *printf_func = 500 gcc_jit_context_new_function (ctxt, NULL, 501 GCC_JIT_FUNCTION_IMPORTED, 502 gcc_jit_context_get_type ( 503 ctxt, GCC_JIT_TYPE_INT), 504 "printf", 505 1, ¶m_format, 506 1); 507 gcc_jit_rvalue *args[2]; 508 args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n"); 509 args[1] = gcc_jit_param_as_rvalue (param_name); 510 511 gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 512 513 gcc_jit_block_add_eval ( 514 block, NULL, 515 gcc_jit_context_new_call (ctxt, 516 NULL, 517 printf_func, 518 2, args)); 519 gcc_jit_block_end_with_void_return (block, NULL); 520@} 521 522int 523main (int argc, char **argv) 524@{ 525 gcc_jit_context *ctxt; 526 gcc_jit_result *result; 527 528 /* Get a "context" object for working with the library. */ 529 ctxt = gcc_jit_context_acquire (); 530 if (!ctxt) 531 @{ 532 fprintf (stderr, "NULL ctxt"); 533 exit (1); 534 @} 535 536 /* Set some options on the context. 537 Let's see the code being generated, in assembler form. */ 538 gcc_jit_context_set_bool_option ( 539 ctxt, 540 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 541 0); 542 543 /* Populate the context. */ 544 create_code (ctxt); 545 546 /* Compile the code. */ 547 result = gcc_jit_context_compile (ctxt); 548 if (!result) 549 @{ 550 fprintf (stderr, "NULL result"); 551 exit (1); 552 @} 553 554 /* Extract the generated code from "result". */ 555 typedef void (*fn_type) (const char *); 556 fn_type greet = 557 (fn_type)gcc_jit_result_get_code (result, "greet"); 558 if (!greet) 559 @{ 560 fprintf (stderr, "NULL greet"); 561 exit (1); 562 @} 563 564 /* Now call the generated function: */ 565 greet ("world"); 566 fflush (stdout); 567 568 gcc_jit_context_release (ctxt); 569 gcc_jit_result_release (result); 570 return 0; 571@} 572@end example 573@end quotation 574 575Copy the above to @cite{tut01-hello-world.c}. 576 577Assuming you have the jit library installed, build the test program 578using: 579 580@example 581$ gcc \ 582 tut01-hello-world.c \ 583 -o tut01-hello-world \ 584 -lgccjit 585@end example 586 587You should then be able to run the built program: 588 589@example 590$ ./tut01-hello-world 591hello world 592@end example 593 594@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 595@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 596@c 597@c This is free software: you can redistribute it and/or modify it 598@c under the terms of the GNU General Public License as published by 599@c the Free Software Foundation, either version 3 of the License, or 600@c (at your option) any later version. 601@c 602@c This program is distributed in the hope that it will be useful, but 603@c WITHOUT ANY WARRANTY; without even the implied warranty of 604@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 605@c General Public License for more details. 606@c 607@c You should have received a copy of the GNU General Public License 608@c along with this program. If not, see 609@c <http://www.gnu.org/licenses/>. 610 611@node Tutorial part 2 Creating a trivial machine code function,Tutorial part 3 Loops and variables,Tutorial part 1 “Hello world”,Tutorial 612@anchor{intro/tutorial02 doc}@anchor{6}@anchor{intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{7} 613@section Tutorial part 2: Creating a trivial machine code function 614 615 616Consider this C function: 617 618@example 619int square (int i) 620@{ 621 return i * i; 622@} 623@end example 624 625How can we construct this at run-time using libgccjit? 626 627First we need to include the relevant header: 628 629@example 630#include <libgccjit.h> 631@end example 632 633All state associated with compilation is associated with a 634@ref{8,,gcc_jit_context *}. 635 636Create one using @ref{9,,gcc_jit_context_acquire()}: 637 638@example 639gcc_jit_context *ctxt; 640ctxt = gcc_jit_context_acquire (); 641@end example 642 643The JIT library has a system of types. It is statically-typed: every 644expression is of a specific type, fixed at compile-time. In our example, 645all of the expressions are of the C @cite{int} type, so let’s obtain this from 646the context, as a @ref{a,,gcc_jit_type *}, using 647@ref{b,,gcc_jit_context_get_type()}: 648 649@example 650gcc_jit_type *int_type = 651 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 652@end example 653 654@ref{a,,gcc_jit_type *} is an example of a “contextual” object: every 655entity in the API is associated with a @ref{8,,gcc_jit_context *}. 656 657Memory management is easy: all such “contextual” objects are automatically 658cleaned up for you when the context is released, using 659@ref{c,,gcc_jit_context_release()}: 660 661@example 662gcc_jit_context_release (ctxt); 663@end example 664 665so you don’t need to manually track and cleanup all objects, just the 666contexts. 667 668Although the API is C-based, there is a form of class hierarchy, which 669looks like this: 670 671@example 672+- gcc_jit_object 673 +- gcc_jit_location 674 +- gcc_jit_type 675 +- gcc_jit_struct 676 +- gcc_jit_field 677 +- gcc_jit_function 678 +- gcc_jit_block 679 +- gcc_jit_rvalue 680 +- gcc_jit_lvalue 681 +- gcc_jit_param 682@end example 683 684There are casting methods for upcasting from subclasses to parent classes. 685For example, @ref{d,,gcc_jit_type_as_object()}: 686 687@example 688gcc_jit_object *obj = gcc_jit_type_as_object (int_type); 689@end example 690 691One thing you can do with a @ref{e,,gcc_jit_object *} is 692to ask it for a human-readable description, using 693@ref{f,,gcc_jit_object_get_debug_string()}: 694 695@example 696printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj)); 697@end example 698 699giving this text on stdout: 700 701@example 702obj: int 703@end example 704 705This is invaluable when debugging. 706 707Let’s create the function. To do so, we first need to construct 708its single parameter, specifying its type and giving it a name, 709using @ref{10,,gcc_jit_context_new_param()}: 710 711@example 712gcc_jit_param *param_i = 713 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 714@end example 715 716Now we can create the function, using 717@ref{11,,gcc_jit_context_new_function()}: 718 719@example 720gcc_jit_function *func = 721 gcc_jit_context_new_function (ctxt, NULL, 722 GCC_JIT_FUNCTION_EXPORTED, 723 int_type, 724 "square", 725 1, ¶m_i, 726 0); 727@end example 728 729To define the code within the function, we must create basic blocks 730containing statements. 731 732Every basic block contains a list of statements, eventually terminated 733by a statement that either returns, or jumps to another basic block. 734 735Our function has no control-flow, so we just need one basic block: 736 737@example 738gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 739@end example 740 741Our basic block is relatively simple: it immediately terminates by 742returning the value of an expression. 743 744We can build the expression using @ref{12,,gcc_jit_context_new_binary_op()}: 745 746@example 747gcc_jit_rvalue *expr = 748 gcc_jit_context_new_binary_op ( 749 ctxt, NULL, 750 GCC_JIT_BINARY_OP_MULT, int_type, 751 gcc_jit_param_as_rvalue (param_i), 752 gcc_jit_param_as_rvalue (param_i)); 753@end example 754 755A @ref{13,,gcc_jit_rvalue *} is another example of a 756@ref{e,,gcc_jit_object *} subclass. We can upcast it using 757@ref{14,,gcc_jit_rvalue_as_object()} and as before print it with 758@ref{f,,gcc_jit_object_get_debug_string()}. 759 760@example 761printf ("expr: %s\n", 762 gcc_jit_object_get_debug_string ( 763 gcc_jit_rvalue_as_object (expr))); 764@end example 765 766giving this output: 767 768@example 769expr: i * i 770@end example 771 772Creating the expression in itself doesn’t do anything; we have to add 773this expression to a statement within the block. In this case, we use it 774to build a return statement, which terminates the basic block: 775 776@example 777gcc_jit_block_end_with_return (block, NULL, expr); 778@end example 779 780OK, we’ve populated the context. We can now compile it using 781@ref{15,,gcc_jit_context_compile()}: 782 783@example 784gcc_jit_result *result; 785result = gcc_jit_context_compile (ctxt); 786@end example 787 788and get a @ref{16,,gcc_jit_result *}. 789 790At this point we’re done with the context; we can release it: 791 792@example 793gcc_jit_context_release (ctxt); 794@end example 795 796We can now use @ref{17,,gcc_jit_result_get_code()} to look up a specific 797machine code routine within the result, in this case, the function we 798created above. 799 800@example 801void *fn_ptr = gcc_jit_result_get_code (result, "square"); 802if (!fn_ptr) 803 @{ 804 fprintf (stderr, "NULL fn_ptr"); 805 goto error; 806 @} 807@end example 808 809We can now cast the pointer to an appropriate function pointer type, and 810then call it: 811 812@example 813typedef int (*fn_type) (int); 814fn_type square = (fn_type)fn_ptr; 815printf ("result: %d", square (5)); 816@end example 817 818@example 819result: 25 820@end example 821 822Once we’re done with the code, we can release the result: 823 824@example 825gcc_jit_result_release (result); 826@end example 827 828We can’t call @code{square} anymore once we’ve released @code{result}. 829 830@menu 831* Error-handling:: 832* Options:: 833* Full example:: 834 835@end menu 836 837@node Error-handling,Options,,Tutorial part 2 Creating a trivial machine code function 838@anchor{intro/tutorial02 error-handling}@anchor{18} 839@subsection Error-handling 840 841 842Various kinds of errors are possible when using the API, such as 843mismatched types in an assignment. You can only compile and get code 844from a context if no errors occur. 845 846Errors are printed on stderr; they typically contain the name of the API 847entrypoint where the error occurred, and pertinent information on the 848problem: 849 850@example 851./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *) 852@end example 853 854The API is designed to cope with errors without crashing, so you can get 855away with having a single error-handling check in your code: 856 857@example 858void *fn_ptr = gcc_jit_result_get_code (result, "square"); 859if (!fn_ptr) 860 @{ 861 fprintf (stderr, "NULL fn_ptr"); 862 goto error; 863 @} 864@end example 865 866For more information, see the @ref{19,,error-handling guide} 867within the Topic eference. 868 869@node Options,Full example,Error-handling,Tutorial part 2 Creating a trivial machine code function 870@anchor{intro/tutorial02 options}@anchor{1a} 871@subsection Options 872 873 874To get more information on what’s going on, you can set debugging flags 875on the context using @ref{1b,,gcc_jit_context_set_bool_option()}. 876 877@c (I'm deliberately not mentioning 878@c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think 879@c it's probably more of use to implementors than to users) 880 881Setting @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE} will dump a 882C-like representation to stderr when you compile (GCC’s “GIMPLE” 883representation): 884 885@example 886gcc_jit_context_set_bool_option ( 887 ctxt, 888 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 889 1); 890result = gcc_jit_context_compile (ctxt); 891@end example 892 893@example 894square (signed int i) 895@{ 896 signed int D.260; 897 898 entry: 899 D.260 = i * i; 900 return D.260; 901@} 902@end example 903 904We can see the generated machine code in assembler form (on stderr) by 905setting @ref{1d,,GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE} on the context 906before compiling: 907 908@example 909gcc_jit_context_set_bool_option ( 910 ctxt, 911 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 912 1); 913result = gcc_jit_context_compile (ctxt); 914@end example 915 916@example 917 .file "fake.c" 918 .text 919 .globl square 920 .type square, @@function 921square: 922.LFB6: 923 .cfi_startproc 924 pushq %rbp 925 .cfi_def_cfa_offset 16 926 .cfi_offset 6, -16 927 movq %rsp, %rbp 928 .cfi_def_cfa_register 6 929 movl %edi, -4(%rbp) 930.L14: 931 movl -4(%rbp), %eax 932 imull -4(%rbp), %eax 933 popq %rbp 934 .cfi_def_cfa 7, 8 935 ret 936 .cfi_endproc 937.LFE6: 938 .size square, .-square 939 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 940 .section .note.GNU-stack,"",@@progbits 941@end example 942 943By default, no optimizations are performed, the equivalent of GCC’s 944@cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling 945@ref{1e,,gcc_jit_context_set_int_option()} with 946@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 947 948@example 949gcc_jit_context_set_int_option ( 950 ctxt, 951 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 952 3); 953@end example 954 955@example 956 .file "fake.c" 957 .text 958 .p2align 4,,15 959 .globl square 960 .type square, @@function 961square: 962.LFB7: 963 .cfi_startproc 964.L16: 965 movl %edi, %eax 966 imull %edi, %eax 967 ret 968 .cfi_endproc 969.LFE7: 970 .size square, .-square 971 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 972 .section .note.GNU-stack,"",@@progbits 973@end example 974 975Naturally this has only a small effect on such a trivial function. 976 977@node Full example,,Options,Tutorial part 2 Creating a trivial machine code function 978@anchor{intro/tutorial02 full-example}@anchor{20} 979@subsection Full example 980 981 982Here’s what the above looks like as a complete program: 983 984@quotation 985 986@example 987/* Usage example for libgccjit.so 988 Copyright (C) 2014-2021 Free Software Foundation, Inc. 989 990This file is part of GCC. 991 992GCC is free software; you can redistribute it and/or modify it 993under the terms of the GNU General Public License as published by 994the Free Software Foundation; either version 3, or (at your option) 995any later version. 996 997GCC is distributed in the hope that it will be useful, but 998WITHOUT ANY WARRANTY; without even the implied warranty of 999MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1000General Public License for more details. 1001 1002You should have received a copy of the GNU General Public License 1003along with GCC; see the file COPYING3. If not see 1004<http://www.gnu.org/licenses/>. */ 1005 1006#include <libgccjit.h> 1007 1008#include <stdlib.h> 1009#include <stdio.h> 1010 1011void 1012create_code (gcc_jit_context *ctxt) 1013@{ 1014 /* Let's try to inject the equivalent of: 1015 1016 int square (int i) 1017 @{ 1018 return i * i; 1019 @} 1020 */ 1021 gcc_jit_type *int_type = 1022 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1023 gcc_jit_param *param_i = 1024 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 1025 gcc_jit_function *func = 1026 gcc_jit_context_new_function (ctxt, NULL, 1027 GCC_JIT_FUNCTION_EXPORTED, 1028 int_type, 1029 "square", 1030 1, ¶m_i, 1031 0); 1032 1033 gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); 1034 1035 gcc_jit_rvalue *expr = 1036 gcc_jit_context_new_binary_op ( 1037 ctxt, NULL, 1038 GCC_JIT_BINARY_OP_MULT, int_type, 1039 gcc_jit_param_as_rvalue (param_i), 1040 gcc_jit_param_as_rvalue (param_i)); 1041 1042 gcc_jit_block_end_with_return (block, NULL, expr); 1043@} 1044 1045int 1046main (int argc, char **argv) 1047@{ 1048 gcc_jit_context *ctxt = NULL; 1049 gcc_jit_result *result = NULL; 1050 1051 /* Get a "context" object for working with the library. */ 1052 ctxt = gcc_jit_context_acquire (); 1053 if (!ctxt) 1054 @{ 1055 fprintf (stderr, "NULL ctxt"); 1056 goto error; 1057 @} 1058 1059 /* Set some options on the context. 1060 Let's see the code being generated, in assembler form. */ 1061 gcc_jit_context_set_bool_option ( 1062 ctxt, 1063 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1064 0); 1065 1066 /* Populate the context. */ 1067 create_code (ctxt); 1068 1069 /* Compile the code. */ 1070 result = gcc_jit_context_compile (ctxt); 1071 if (!result) 1072 @{ 1073 fprintf (stderr, "NULL result"); 1074 goto error; 1075 @} 1076 1077 /* We're done with the context; we can release it: */ 1078 gcc_jit_context_release (ctxt); 1079 ctxt = NULL; 1080 1081 /* Extract the generated code from "result". */ 1082 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 1083 if (!fn_ptr) 1084 @{ 1085 fprintf (stderr, "NULL fn_ptr"); 1086 goto error; 1087 @} 1088 1089 typedef int (*fn_type) (int); 1090 fn_type square = (fn_type)fn_ptr; 1091 printf ("result: %d\n", square (5)); 1092 1093 error: 1094 if (ctxt) 1095 gcc_jit_context_release (ctxt); 1096 if (result) 1097 gcc_jit_result_release (result); 1098 return 0; 1099@} 1100@end example 1101@end quotation 1102 1103Building and running it: 1104 1105@example 1106$ gcc \ 1107 tut02-square.c \ 1108 -o tut02-square \ 1109 -lgccjit 1110 1111# Run the built program: 1112$ ./tut02-square 1113result: 25 1114@end example 1115 1116@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 1117@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 1118@c 1119@c This is free software: you can redistribute it and/or modify it 1120@c under the terms of the GNU General Public License as published by 1121@c the Free Software Foundation, either version 3 of the License, or 1122@c (at your option) any later version. 1123@c 1124@c This program is distributed in the hope that it will be useful, but 1125@c WITHOUT ANY WARRANTY; without even the implied warranty of 1126@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1127@c General Public License for more details. 1128@c 1129@c You should have received a copy of the GNU General Public License 1130@c along with this program. If not, see 1131@c <http://www.gnu.org/licenses/>. 1132 1133@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 1134@anchor{intro/tutorial03 doc}@anchor{21}@anchor{intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{22} 1135@section Tutorial part 3: Loops and variables 1136 1137 1138Consider this C function: 1139 1140@quotation 1141 1142@example 1143int loop_test (int n) 1144@{ 1145 int sum = 0; 1146 for (int i = 0; i < n; i++) 1147 sum += i * i; 1148 return sum; 1149@} 1150@end example 1151@end quotation 1152 1153This example demonstrates some more features of libgccjit, with local 1154variables and a loop. 1155 1156To break this down into libgccjit terms, it’s usually easier to reword 1157the @cite{for} loop as a @cite{while} loop, giving: 1158 1159@quotation 1160 1161@example 1162int loop_test (int n) 1163@{ 1164 int sum = 0; 1165 int i = 0; 1166 while (i < n) 1167 @{ 1168 sum += i * i; 1169 i++; 1170 @} 1171 return sum; 1172@} 1173@end example 1174@end quotation 1175 1176Here’s what the final control flow graph will look like: 1177 1178@quotation 1179 1180 1181@float Figure 1182 1183@image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png} 1184 1185@end float 1186 1187@end quotation 1188 1189As before, we include the libgccjit header and make a 1190@ref{8,,gcc_jit_context *}. 1191 1192@example 1193#include <libgccjit.h> 1194 1195void test (void) 1196@{ 1197 gcc_jit_context *ctxt; 1198 ctxt = gcc_jit_context_acquire (); 1199@end example 1200 1201The function works with the C @cite{int} type: 1202 1203@example 1204gcc_jit_type *the_type = 1205 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1206gcc_jit_type *return_type = the_type; 1207@end example 1208 1209though we could equally well make it work on, say, @cite{double}: 1210 1211@example 1212gcc_jit_type *the_type = 1213 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); 1214@end example 1215 1216Let’s build the function: 1217 1218@example 1219gcc_jit_param *n = 1220 gcc_jit_context_new_param (ctxt, NULL, the_type, "n"); 1221gcc_jit_param *params[1] = @{n@}; 1222gcc_jit_function *func = 1223 gcc_jit_context_new_function (ctxt, NULL, 1224 GCC_JIT_FUNCTION_EXPORTED, 1225 return_type, 1226 "loop_test", 1227 1, params, 0); 1228@end example 1229 1230@menu 1231* Expressions; lvalues and rvalues: Expressions lvalues and rvalues. 1232* Control flow:: 1233* Visualizing the control flow graph:: 1234* Full example: Full example<2>. 1235 1236@end menu 1237 1238@node Expressions lvalues and rvalues,Control flow,,Tutorial part 3 Loops and variables 1239@anchor{intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{23} 1240@subsection Expressions: lvalues and rvalues 1241 1242 1243The base class of expression is the @ref{13,,gcc_jit_rvalue *}, 1244representing an expression that can be on the @emph{right}-hand side of 1245an assignment: a value that can be computed somehow, and assigned 1246@emph{to} a storage area (such as a variable). It has a specific 1247@ref{a,,gcc_jit_type *}. 1248 1249Anothe important class is @ref{24,,gcc_jit_lvalue *}. 1250A @ref{24,,gcc_jit_lvalue *}. is something that can of the @emph{left}-hand 1251side of an assignment: a storage area (such as a variable). 1252 1253In other words, every assignment can be thought of as: 1254 1255@example 1256LVALUE = RVALUE; 1257@end example 1258 1259Note that @ref{24,,gcc_jit_lvalue *} is a subclass of 1260@ref{13,,gcc_jit_rvalue *}, where in an assignment of the form: 1261 1262@example 1263LVALUE_A = LVALUE_B; 1264@end example 1265 1266the @cite{LVALUE_B} implies reading the current value of that storage 1267area, assigning it into the @cite{LVALUE_A}. 1268 1269So far the only expressions we’ve seen are @cite{i * i}: 1270 1271@example 1272gcc_jit_rvalue *expr = 1273 gcc_jit_context_new_binary_op ( 1274 ctxt, NULL, 1275 GCC_JIT_BINARY_OP_MULT, int_type, 1276 gcc_jit_param_as_rvalue (param_i), 1277 gcc_jit_param_as_rvalue (param_i)); 1278@end example 1279 1280which is a @ref{13,,gcc_jit_rvalue *}, and the various function 1281parameters: @cite{param_i} and @cite{param_n}, instances of 1282@ref{25,,gcc_jit_param *}, which is a subclass of 1283@ref{24,,gcc_jit_lvalue *} (and, in turn, of @ref{13,,gcc_jit_rvalue *}): 1284we can both read from and write to function parameters within the 1285body of a function. 1286 1287Our new example has a couple of local variables. We create them by 1288calling @ref{26,,gcc_jit_function_new_local()}, supplying a type and a 1289name: 1290 1291@example 1292/* Build locals: */ 1293gcc_jit_lvalue *i = 1294 gcc_jit_function_new_local (func, NULL, the_type, "i"); 1295gcc_jit_lvalue *sum = 1296 gcc_jit_function_new_local (func, NULL, the_type, "sum"); 1297@end example 1298 1299These are instances of @ref{24,,gcc_jit_lvalue *} - they can be read from 1300and written to. 1301 1302Note that there is no precanned way to create @emph{and} initialize a variable 1303like in C: 1304 1305@example 1306int i = 0; 1307@end example 1308 1309Instead, having added the local to the function, we have to separately add 1310an assignment of @cite{0} to @cite{local_i} at the beginning of the function. 1311 1312@node Control flow,Visualizing the control flow graph,Expressions lvalues and rvalues,Tutorial part 3 Loops and variables 1313@anchor{intro/tutorial03 control-flow}@anchor{27} 1314@subsection Control flow 1315 1316 1317This function has a loop, so we need to build some basic blocks to 1318handle the control flow. In this case, we need 4 blocks: 1319 1320 1321@enumerate 1322 1323@item 1324before the loop (initializing the locals) 1325 1326@item 1327the conditional at the top of the loop (comparing @cite{i < n}) 1328 1329@item 1330the body of the loop 1331 1332@item 1333after the loop terminates (@cite{return sum}) 1334@end enumerate 1335 1336so we create these as @ref{28,,gcc_jit_block *} instances within the 1337@ref{29,,gcc_jit_function *}: 1338 1339@example 1340gcc_jit_block *b_initial = 1341 gcc_jit_function_new_block (func, "initial"); 1342gcc_jit_block *b_loop_cond = 1343 gcc_jit_function_new_block (func, "loop_cond"); 1344gcc_jit_block *b_loop_body = 1345 gcc_jit_function_new_block (func, "loop_body"); 1346gcc_jit_block *b_after_loop = 1347 gcc_jit_function_new_block (func, "after_loop"); 1348@end example 1349 1350We now populate each block with statements. 1351 1352The entry block @cite{b_initial} consists of initializations followed by a jump 1353to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using 1354@ref{2a,,gcc_jit_block_add_assignment()} to add 1355an assignment statement, and using @ref{2b,,gcc_jit_context_zero()} to get 1356the constant value @cite{0} for the relevant type for the right-hand side of 1357the assignment: 1358 1359@example 1360/* sum = 0; */ 1361gcc_jit_block_add_assignment ( 1362 b_initial, NULL, 1363 sum, 1364 gcc_jit_context_zero (ctxt, the_type)); 1365 1366/* i = 0; */ 1367gcc_jit_block_add_assignment ( 1368 b_initial, NULL, 1369 i, 1370 gcc_jit_context_zero (ctxt, the_type)); 1371@end example 1372 1373We can then terminate the entry block by jumping to the conditional: 1374 1375@example 1376gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond); 1377@end example 1378 1379The conditional block is equivalent to the line @cite{while (i < n)} from our 1380C example. It contains a single statement: a conditional, which jumps to 1381one of two destination blocks depending on a boolean 1382@ref{13,,gcc_jit_rvalue *}, in this case the comparison of @cite{i} and @cite{n}. 1383We build the comparison using @ref{2c,,gcc_jit_context_new_comparison()}: 1384 1385@example 1386/* (i >= n) */ 1387 gcc_jit_rvalue *guard = 1388 gcc_jit_context_new_comparison ( 1389 ctxt, NULL, 1390 GCC_JIT_COMPARISON_GE, 1391 gcc_jit_lvalue_as_rvalue (i), 1392 gcc_jit_param_as_rvalue (n)); 1393@end example 1394 1395and can then use this to add @cite{b_loop_cond}’s sole statement, via 1396@ref{2d,,gcc_jit_block_end_with_conditional()}: 1397 1398@example 1399/* Equivalent to: 1400 if (guard) 1401 goto after_loop; 1402 else 1403 goto loop_body; */ 1404gcc_jit_block_end_with_conditional ( 1405 b_loop_cond, NULL, 1406 guard, 1407 b_after_loop, /* on_true */ 1408 b_loop_body); /* on_false */ 1409@end example 1410 1411Next, we populate the body of the loop. 1412 1413The C statement @cite{sum += i * i;} is an assignment operation, where an 1414lvalue is modified “in-place”. We use 1415@ref{2e,,gcc_jit_block_add_assignment_op()} to handle these operations: 1416 1417@example 1418/* sum += i * i */ 1419gcc_jit_block_add_assignment_op ( 1420 b_loop_body, NULL, 1421 sum, 1422 GCC_JIT_BINARY_OP_PLUS, 1423 gcc_jit_context_new_binary_op ( 1424 ctxt, NULL, 1425 GCC_JIT_BINARY_OP_MULT, the_type, 1426 gcc_jit_lvalue_as_rvalue (i), 1427 gcc_jit_lvalue_as_rvalue (i))); 1428@end example 1429 1430The @cite{i++} can be thought of as @cite{i += 1}, and can thus be handled in 1431a similar way. We use @ref{2f,,gcc_jit_context_one()} to get the constant 1432value @cite{1} (for the relevant type) for the right-hand side 1433of the assignment. 1434 1435@example 1436/* i++ */ 1437gcc_jit_block_add_assignment_op ( 1438 b_loop_body, NULL, 1439 i, 1440 GCC_JIT_BINARY_OP_PLUS, 1441 gcc_jit_context_one (ctxt, the_type)); 1442@end example 1443 1444@cartouche 1445@quotation Note 1446For numeric constants other than 0 or 1, we could use 1447@ref{30,,gcc_jit_context_new_rvalue_from_int()} and 1448@ref{31,,gcc_jit_context_new_rvalue_from_double()}. 1449@end quotation 1450@end cartouche 1451 1452The loop body completes by jumping back to the conditional: 1453 1454@example 1455gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond); 1456@end example 1457 1458Finally, we populate the @cite{b_after_loop} block, reached when the loop 1459conditional is false. We want to generate the equivalent of: 1460 1461@example 1462return sum; 1463@end example 1464 1465so the block is just one statement: 1466 1467@example 1468/* return sum */ 1469gcc_jit_block_end_with_return ( 1470 b_after_loop, 1471 NULL, 1472 gcc_jit_lvalue_as_rvalue (sum)); 1473@end example 1474 1475@cartouche 1476@quotation Note 1477You can intermingle block creation with statement creation, 1478but given that the terminator statements generally include references 1479to other blocks, I find it’s clearer to create all the blocks, 1480@emph{then} all the statements. 1481@end quotation 1482@end cartouche 1483 1484We’ve finished populating the function. As before, we can now compile it 1485to machine code: 1486 1487@example 1488gcc_jit_result *result; 1489result = gcc_jit_context_compile (ctxt); 1490 1491typedef int (*loop_test_fn_type) (int); 1492loop_test_fn_type loop_test = 1493 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 1494if (!loop_test) 1495 goto error; 1496printf ("result: %d", loop_test (10)); 1497@end example 1498 1499@example 1500result: 285 1501@end example 1502 1503@node Visualizing the control flow graph,Full example<2>,Control flow,Tutorial part 3 Loops and variables 1504@anchor{intro/tutorial03 visualizing-the-control-flow-graph}@anchor{32} 1505@subsection Visualizing the control flow graph 1506 1507 1508You can see the control flow graph of a function using 1509@ref{33,,gcc_jit_function_dump_to_dot()}: 1510 1511@example 1512gcc_jit_function_dump_to_dot (func, "/tmp/sum-of-squares.dot"); 1513@end example 1514 1515giving a .dot file in GraphViz format. 1516 1517You can convert this to an image using @cite{dot}: 1518 1519@example 1520$ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png 1521@end example 1522 1523or use a viewer (my preferred one is xdot.py; see 1524@indicateurl{https://github.com/jrfonseca/xdot.py}; on Fedora you can 1525install it with @cite{yum install python-xdot}): 1526 1527@quotation 1528 1529 1530@float Figure 1531 1532@image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png} 1533 1534@end float 1535 1536@end quotation 1537 1538@node Full example<2>,,Visualizing the control flow graph,Tutorial part 3 Loops and variables 1539@anchor{intro/tutorial03 full-example}@anchor{34} 1540@subsection Full example 1541 1542 1543@quotation 1544 1545@example 1546/* Usage example for libgccjit.so 1547 Copyright (C) 2014-2021 Free Software Foundation, Inc. 1548 1549This file is part of GCC. 1550 1551GCC is free software; you can redistribute it and/or modify it 1552under the terms of the GNU General Public License as published by 1553the Free Software Foundation; either version 3, or (at your option) 1554any later version. 1555 1556GCC is distributed in the hope that it will be useful, but 1557WITHOUT ANY WARRANTY; without even the implied warranty of 1558MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1559General Public License for more details. 1560 1561You should have received a copy of the GNU General Public License 1562along with GCC; see the file COPYING3. If not see 1563<http://www.gnu.org/licenses/>. */ 1564 1565#include <libgccjit.h> 1566 1567#include <stdlib.h> 1568#include <stdio.h> 1569 1570void 1571create_code (gcc_jit_context *ctxt) 1572@{ 1573 /* 1574 Simple sum-of-squares, to test conditionals and looping 1575 1576 int loop_test (int n) 1577 @{ 1578 int i; 1579 int sum = 0; 1580 for (i = 0; i < n ; i ++) 1581 @{ 1582 sum += i * i; 1583 @} 1584 return sum; 1585 */ 1586 gcc_jit_type *the_type = 1587 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 1588 gcc_jit_type *return_type = the_type; 1589 1590 gcc_jit_param *n = 1591 gcc_jit_context_new_param (ctxt, NULL, the_type, "n"); 1592 gcc_jit_param *params[1] = @{n@}; 1593 gcc_jit_function *func = 1594 gcc_jit_context_new_function (ctxt, NULL, 1595 GCC_JIT_FUNCTION_EXPORTED, 1596 return_type, 1597 "loop_test", 1598 1, params, 0); 1599 1600 /* Build locals: */ 1601 gcc_jit_lvalue *i = 1602 gcc_jit_function_new_local (func, NULL, the_type, "i"); 1603 gcc_jit_lvalue *sum = 1604 gcc_jit_function_new_local (func, NULL, the_type, "sum"); 1605 1606 gcc_jit_block *b_initial = 1607 gcc_jit_function_new_block (func, "initial"); 1608 gcc_jit_block *b_loop_cond = 1609 gcc_jit_function_new_block (func, "loop_cond"); 1610 gcc_jit_block *b_loop_body = 1611 gcc_jit_function_new_block (func, "loop_body"); 1612 gcc_jit_block *b_after_loop = 1613 gcc_jit_function_new_block (func, "after_loop"); 1614 1615 /* sum = 0; */ 1616 gcc_jit_block_add_assignment ( 1617 b_initial, NULL, 1618 sum, 1619 gcc_jit_context_zero (ctxt, the_type)); 1620 1621 /* i = 0; */ 1622 gcc_jit_block_add_assignment ( 1623 b_initial, NULL, 1624 i, 1625 gcc_jit_context_zero (ctxt, the_type)); 1626 1627 gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond); 1628 1629 /* if (i >= n) */ 1630 gcc_jit_block_end_with_conditional ( 1631 b_loop_cond, NULL, 1632 gcc_jit_context_new_comparison ( 1633 ctxt, NULL, 1634 GCC_JIT_COMPARISON_GE, 1635 gcc_jit_lvalue_as_rvalue (i), 1636 gcc_jit_param_as_rvalue (n)), 1637 b_after_loop, 1638 b_loop_body); 1639 1640 /* sum += i * i */ 1641 gcc_jit_block_add_assignment_op ( 1642 b_loop_body, NULL, 1643 sum, 1644 GCC_JIT_BINARY_OP_PLUS, 1645 gcc_jit_context_new_binary_op ( 1646 ctxt, NULL, 1647 GCC_JIT_BINARY_OP_MULT, the_type, 1648 gcc_jit_lvalue_as_rvalue (i), 1649 gcc_jit_lvalue_as_rvalue (i))); 1650 1651 /* i++ */ 1652 gcc_jit_block_add_assignment_op ( 1653 b_loop_body, NULL, 1654 i, 1655 GCC_JIT_BINARY_OP_PLUS, 1656 gcc_jit_context_one (ctxt, the_type)); 1657 1658 gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond); 1659 1660 /* return sum */ 1661 gcc_jit_block_end_with_return ( 1662 b_after_loop, 1663 NULL, 1664 gcc_jit_lvalue_as_rvalue (sum)); 1665@} 1666 1667int 1668main (int argc, char **argv) 1669@{ 1670 gcc_jit_context *ctxt = NULL; 1671 gcc_jit_result *result = NULL; 1672 1673 /* Get a "context" object for working with the library. */ 1674 ctxt = gcc_jit_context_acquire (); 1675 if (!ctxt) 1676 @{ 1677 fprintf (stderr, "NULL ctxt"); 1678 goto error; 1679 @} 1680 1681 /* Set some options on the context. 1682 Let's see the code being generated, in assembler form. */ 1683 gcc_jit_context_set_bool_option ( 1684 ctxt, 1685 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1686 0); 1687 1688 /* Populate the context. */ 1689 create_code (ctxt); 1690 1691 /* Compile the code. */ 1692 result = gcc_jit_context_compile (ctxt); 1693 if (!result) 1694 @{ 1695 fprintf (stderr, "NULL result"); 1696 goto error; 1697 @} 1698 1699 /* Extract the generated code from "result". */ 1700 typedef int (*loop_test_fn_type) (int); 1701 loop_test_fn_type loop_test = 1702 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 1703 if (!loop_test) 1704 @{ 1705 fprintf (stderr, "NULL loop_test"); 1706 goto error; 1707 @} 1708 1709 /* Run the generated code. */ 1710 int val = loop_test (10); 1711 printf("loop_test returned: %d\n", val); 1712 1713 error: 1714 gcc_jit_context_release (ctxt); 1715 gcc_jit_result_release (result); 1716 return 0; 1717@} 1718@end example 1719@end quotation 1720 1721Building and running it: 1722 1723@example 1724$ gcc \ 1725 tut03-sum-of-squares.c \ 1726 -o tut03-sum-of-squares \ 1727 -lgccjit 1728 1729# Run the built program: 1730$ ./tut03-sum-of-squares 1731loop_test returned: 285 1732@end example 1733 1734@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 1735@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 1736@c 1737@c This is free software: you can redistribute it and/or modify it 1738@c under the terms of the GNU General Public License as published by 1739@c the Free Software Foundation, either version 3 of the License, or 1740@c (at your option) any later version. 1741@c 1742@c This program is distributed in the hope that it will be useful, but 1743@c WITHOUT ANY WARRANTY; without even the implied warranty of 1744@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1745@c General Public License for more details. 1746@c 1747@c You should have received a copy of the GNU General Public License 1748@c along with this program. If not, see 1749@c <http://www.gnu.org/licenses/>. 1750 1751@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 1752@anchor{intro/tutorial04 doc}@anchor{35}@anchor{intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{36} 1753@section Tutorial part 4: Adding JIT-compilation to a toy interpreter 1754 1755 1756In this example we construct a “toy” interpreter, and add JIT-compilation 1757to it. 1758 1759@menu 1760* Our toy interpreter:: 1761* Compiling to machine code:: 1762* Setting things up:: 1763* Populating the function:: 1764* Verifying the control flow graph:: 1765* Compiling the context:: 1766* Single-stepping through the generated code:: 1767* Examining the generated code:: 1768* Putting it all together:: 1769* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?. 1770 1771@end menu 1772 1773@node Our toy interpreter,Compiling to machine code,,Tutorial part 4 Adding JIT-compilation to a toy interpreter 1774@anchor{intro/tutorial04 our-toy-interpreter}@anchor{37} 1775@subsection Our toy interpreter 1776 1777 1778It’s a stack-based interpreter, and is intended as a (very simple) example 1779of the kind of bytecode interpreter seen in dynamic languages such as 1780Python, Ruby etc. 1781 1782For the sake of simplicity, our toy virtual machine is very limited: 1783 1784@quotation 1785 1786 1787@itemize * 1788 1789@item 1790The only data type is @cite{int} 1791 1792@item 1793It can only work on one function at a time (so that the only 1794function call that can be made is to recurse). 1795 1796@item 1797Functions can only take one parameter. 1798 1799@item 1800Functions have a stack of @cite{int} values. 1801 1802@item 1803We’ll implement function call within the interpreter by calling a 1804function in our implementation, rather than implementing our own 1805frame stack. 1806 1807@item 1808The parser is only good enough to get the examples to work. 1809@end itemize 1810@end quotation 1811 1812Naturally, a real interpreter would be much more complicated that this. 1813 1814The following operations are supported: 1815 1816 1817@multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxx} 1818@headitem 1819 1820Operation 1821 1822@tab 1823 1824Meaning 1825 1826@tab 1827 1828Old Stack 1829 1830@tab 1831 1832New Stack 1833 1834@item 1835 1836DUP 1837 1838@tab 1839 1840Duplicate top of stack. 1841 1842@tab 1843 1844@code{[..., x]} 1845 1846@tab 1847 1848@code{[..., x, x]} 1849 1850@item 1851 1852ROT 1853 1854@tab 1855 1856Swap top two elements 1857of stack. 1858 1859@tab 1860 1861@code{[..., x, y]} 1862 1863@tab 1864 1865@code{[..., y, x]} 1866 1867@item 1868 1869BINARY_ADD 1870 1871@tab 1872 1873Add the top two elements 1874on the stack. 1875 1876@tab 1877 1878@code{[..., x, y]} 1879 1880@tab 1881 1882@code{[..., (x+y)]} 1883 1884@item 1885 1886BINARY_SUBTRACT 1887 1888@tab 1889 1890Likewise, but subtract. 1891 1892@tab 1893 1894@code{[..., x, y]} 1895 1896@tab 1897 1898@code{[..., (x-y)]} 1899 1900@item 1901 1902BINARY_MULT 1903 1904@tab 1905 1906Likewise, but multiply. 1907 1908@tab 1909 1910@code{[..., x, y]} 1911 1912@tab 1913 1914@code{[..., (x*y)]} 1915 1916@item 1917 1918BINARY_COMPARE_LT 1919 1920@tab 1921 1922Compare the top two 1923elements on the stack 1924and push a nonzero/zero 1925if (x<y). 1926 1927@tab 1928 1929@code{[..., x, y]} 1930 1931@tab 1932 1933@code{[..., (x<y)]} 1934 1935@item 1936 1937RECURSE 1938 1939@tab 1940 1941Recurse, passing the top 1942of the stack, and 1943popping the result. 1944 1945@tab 1946 1947@code{[..., x]} 1948 1949@tab 1950 1951@code{[..., fn(x)]} 1952 1953@item 1954 1955RETURN 1956 1957@tab 1958 1959Return the top of the 1960stack. 1961 1962@tab 1963 1964@code{[x]} 1965 1966@tab 1967 1968@code{[]} 1969 1970@item 1971 1972PUSH_CONST @cite{arg} 1973 1974@tab 1975 1976Push an int const. 1977 1978@tab 1979 1980@code{[...]} 1981 1982@tab 1983 1984@code{[..., arg]} 1985 1986@item 1987 1988JUMP_ABS_IF_TRUE @cite{arg} 1989 1990@tab 1991 1992Pop; if top of stack was 1993nonzero, jump to 1994@code{arg}. 1995 1996@tab 1997 1998@code{[..., x]} 1999 2000@tab 2001 2002@code{[...]} 2003 2004@end multitable 2005 2006 2007Programs can be interpreted, disassembled, and compiled to machine code. 2008 2009The interpreter reads @code{.toy} scripts. Here’s what a simple recursive 2010factorial program looks like, the script @code{factorial.toy}. 2011The parser ignores lines beginning with a @cite{#}. 2012 2013@quotation 2014 2015@example 2016# Simple recursive factorial implementation, roughly equivalent to: 2017# 2018# int factorial (int arg) 2019# @{ 2020# if (arg < 2) 2021# return arg 2022# return arg * factorial (arg - 1) 2023# @} 2024 2025# Initial state: 2026# stack: [arg] 2027 2028# 0: 2029DUP 2030# stack: [arg, arg] 2031 2032# 1: 2033PUSH_CONST 2 2034# stack: [arg, arg, 2] 2035 2036# 2: 2037BINARY_COMPARE_LT 2038# stack: [arg, (arg < 2)] 2039 2040# 3: 2041JUMP_ABS_IF_TRUE 9 2042# stack: [arg] 2043 2044# 4: 2045DUP 2046# stack: [arg, arg] 2047 2048# 5: 2049PUSH_CONST 1 2050# stack: [arg, arg, 1] 2051 2052# 6: 2053BINARY_SUBTRACT 2054# stack: [arg, (arg - 1) 2055 2056# 7: 2057RECURSE 2058# stack: [arg, factorial(arg - 1)] 2059 2060# 8: 2061BINARY_MULT 2062# stack: [arg * factorial(arg - 1)] 2063 2064# 9: 2065RETURN 2066@end example 2067@end quotation 2068 2069The interpreter is a simple infinite loop with a big @code{switch} statement 2070based on what the next opcode is: 2071 2072@quotation 2073 2074@example 2075 2076static int 2077toyvm_function_interpret (toyvm_function *fn, int arg, FILE *trace) 2078@{ 2079 toyvm_frame frame; 2080#define PUSH(ARG) (toyvm_frame_push (&frame, (ARG))) 2081#define POP(ARG) (toyvm_frame_pop (&frame)) 2082 2083 frame.frm_function = fn; 2084 frame.frm_pc = 0; 2085 frame.frm_cur_depth = 0; 2086 2087 PUSH (arg); 2088 2089 while (1) 2090 @{ 2091 toyvm_op *op; 2092 int x, y; 2093 assert (frame.frm_pc < fn->fn_num_ops); 2094 op = &fn->fn_ops[frame.frm_pc++]; 2095 2096 if (trace) 2097 @{ 2098 toyvm_frame_dump_stack (&frame, trace); 2099 toyvm_function_disassemble_op (fn, op, frame.frm_pc, trace); 2100 @} 2101 2102 switch (op->op_opcode) 2103 @{ 2104 /* Ops taking no operand. */ 2105 case DUP: 2106 x = POP (); 2107 PUSH (x); 2108 PUSH (x); 2109 break; 2110 2111 case ROT: 2112 y = POP (); 2113 x = POP (); 2114 PUSH (y); 2115 PUSH (x); 2116 break; 2117 2118 case BINARY_ADD: 2119 y = POP (); 2120 x = POP (); 2121 PUSH (x + y); 2122 break; 2123 2124 case BINARY_SUBTRACT: 2125 y = POP (); 2126 x = POP (); 2127 PUSH (x - y); 2128 break; 2129 2130 case BINARY_MULT: 2131 y = POP (); 2132 x = POP (); 2133 PUSH (x * y); 2134 break; 2135 2136 case BINARY_COMPARE_LT: 2137 y = POP (); 2138 x = POP (); 2139 PUSH (x < y); 2140 break; 2141 2142 case RECURSE: 2143 x = POP (); 2144 x = toyvm_function_interpret (fn, x, trace); 2145 PUSH (x); 2146 break; 2147 2148 case RETURN: 2149 return POP (); 2150 2151 /* Ops taking an operand. */ 2152 case PUSH_CONST: 2153 PUSH (op->op_operand); 2154 break; 2155 2156 case JUMP_ABS_IF_TRUE: 2157 x = POP (); 2158 if (x) 2159 frame.frm_pc = op->op_operand; 2160 break; 2161 2162 default: 2163 assert (0); /* unknown opcode */ 2164 2165 @} /* end of switch on opcode */ 2166 @} /* end of while loop */ 2167 2168#undef PUSH 2169#undef POP 2170@} 2171 2172@end example 2173@end quotation 2174 2175@node Compiling to machine code,Setting things up,Our toy interpreter,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2176@anchor{intro/tutorial04 compiling-to-machine-code}@anchor{38} 2177@subsection Compiling to machine code 2178 2179 2180We want to generate machine code that can be cast to this type and 2181then directly executed in-process: 2182 2183@quotation 2184 2185@example 2186typedef int (*toyvm_compiled_code) (int); 2187 2188@end example 2189@end quotation 2190 2191The lifetime of the code is tied to that of a @ref{16,,gcc_jit_result *}. 2192We’ll handle this by bundling them up in a structure, so that we can 2193clean them up together by calling @ref{39,,gcc_jit_result_release()}: 2194 2195@quotation 2196 2197@example 2198 2199struct toyvm_compiled_function 2200@{ 2201 gcc_jit_result *cf_jit_result; 2202 toyvm_compiled_code cf_code; 2203@}; 2204 2205@end example 2206@end quotation 2207 2208Our compiler isn’t very sophisticated; it takes the implementation of 2209each opcode above, and maps it directly to the operations supported by 2210the libgccjit API. 2211 2212How should we handle the stack? In theory we could calculate what the 2213stack depth will be at each opcode, and optimize away the stack 2214manipulation “by hand”. We’ll see below that libgccjit is able to do 2215this for us, so we’ll implement stack manipulation 2216in a direct way, by creating a @code{stack} array and @code{stack_depth} 2217variables, local within the generated function, equivalent to this C code: 2218 2219@example 2220int stack_depth; 2221int stack[MAX_STACK_DEPTH]; 2222@end example 2223 2224We’ll also have local variables @code{x} and @code{y} for use when implementing 2225the opcodes, equivalent to this: 2226 2227@example 2228int x; 2229int y; 2230@end example 2231 2232This means our compiler has the following state: 2233 2234@quotation 2235 2236@example 2237 2238struct compilation_state 2239@{ 2240 gcc_jit_context *ctxt; 2241 2242 gcc_jit_type *int_type; 2243 gcc_jit_type *bool_type; 2244 gcc_jit_type *stack_type; /* int[MAX_STACK_DEPTH] */ 2245 2246 gcc_jit_rvalue *const_one; 2247 2248 gcc_jit_function *fn; 2249 gcc_jit_param *param_arg; 2250 gcc_jit_lvalue *stack; 2251 gcc_jit_lvalue *stack_depth; 2252 gcc_jit_lvalue *x; 2253 gcc_jit_lvalue *y; 2254 2255 gcc_jit_location *op_locs[MAX_OPS]; 2256 gcc_jit_block *initial_block; 2257 gcc_jit_block *op_blocks[MAX_OPS]; 2258 2259@}; 2260 2261@end example 2262@end quotation 2263 2264@node Setting things up,Populating the function,Compiling to machine code,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2265@anchor{intro/tutorial04 setting-things-up}@anchor{3a} 2266@subsection Setting things up 2267 2268 2269First we create our types: 2270 2271@quotation 2272 2273@example 2274 state.int_type = 2275 gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_INT); 2276 state.bool_type = 2277 gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_BOOL); 2278 state.stack_type = 2279 gcc_jit_context_new_array_type (state.ctxt, NULL, 2280 state.int_type, MAX_STACK_DEPTH); 2281 2282@end example 2283@end quotation 2284 2285along with extracting a useful @cite{int} constant: 2286 2287@quotation 2288 2289@example 2290 state.const_one = gcc_jit_context_one (state.ctxt, state.int_type); 2291 2292@end example 2293@end quotation 2294 2295We’ll implement push and pop in terms of the @code{stack} array and 2296@code{stack_depth}. Here are helper functions for adding statements to 2297a block, implementing pushing and popping values: 2298 2299@quotation 2300 2301@example 2302 2303static void 2304add_push (compilation_state *state, 2305 gcc_jit_block *block, 2306 gcc_jit_rvalue *rvalue, 2307 gcc_jit_location *loc) 2308@{ 2309 /* stack[stack_depth] = RVALUE */ 2310 gcc_jit_block_add_assignment ( 2311 block, 2312 loc, 2313 /* stack[stack_depth] */ 2314 gcc_jit_context_new_array_access ( 2315 state->ctxt, 2316 loc, 2317 gcc_jit_lvalue_as_rvalue (state->stack), 2318 gcc_jit_lvalue_as_rvalue (state->stack_depth)), 2319 rvalue); 2320 2321 /* "stack_depth++;". */ 2322 gcc_jit_block_add_assignment_op ( 2323 block, 2324 loc, 2325 state->stack_depth, 2326 GCC_JIT_BINARY_OP_PLUS, 2327 state->const_one); 2328@} 2329 2330static void 2331add_pop (compilation_state *state, 2332 gcc_jit_block *block, 2333 gcc_jit_lvalue *lvalue, 2334 gcc_jit_location *loc) 2335@{ 2336 /* "--stack_depth;". */ 2337 gcc_jit_block_add_assignment_op ( 2338 block, 2339 loc, 2340 state->stack_depth, 2341 GCC_JIT_BINARY_OP_MINUS, 2342 state->const_one); 2343 2344 /* "LVALUE = stack[stack_depth];". */ 2345 gcc_jit_block_add_assignment ( 2346 block, 2347 loc, 2348 lvalue, 2349 /* stack[stack_depth] */ 2350 gcc_jit_lvalue_as_rvalue ( 2351 gcc_jit_context_new_array_access ( 2352 state->ctxt, 2353 loc, 2354 gcc_jit_lvalue_as_rvalue (state->stack), 2355 gcc_jit_lvalue_as_rvalue (state->stack_depth)))); 2356@} 2357 2358@end example 2359@end quotation 2360 2361We will support single-stepping through the generated code in the 2362debugger, so we need to create @ref{3b,,gcc_jit_location} instances, one 2363per operation in the source code. These will reference the lines of 2364e.g. @code{factorial.toy}. 2365 2366@quotation 2367 2368@example 2369 for (pc = 0; pc < fn->fn_num_ops; pc++) 2370 @{ 2371 toyvm_op *op = &fn->fn_ops[pc]; 2372 2373 state.op_locs[pc] = gcc_jit_context_new_location (state.ctxt, 2374 fn->fn_filename, 2375 op->op_linenum, 2376 0); /* column */ 2377 @} 2378 2379@end example 2380@end quotation 2381 2382Let’s create the function itself. As usual, we create its parameter 2383first, then use the parameter to create the function: 2384 2385@quotation 2386 2387@example 2388 state.param_arg = 2389 gcc_jit_context_new_param (state.ctxt, state.op_locs[0], 2390 state.int_type, "arg"); 2391 state.fn = 2392 gcc_jit_context_new_function (state.ctxt, 2393 state.op_locs[0], 2394 GCC_JIT_FUNCTION_EXPORTED, 2395 state.int_type, 2396 funcname, 2397 1, &state.param_arg, 0); 2398 2399@end example 2400@end quotation 2401 2402We create the locals within the function. 2403 2404@quotation 2405 2406@example 2407 state.stack = 2408 gcc_jit_function_new_local (state.fn, NULL, 2409 state.stack_type, "stack"); 2410 state.stack_depth = 2411 gcc_jit_function_new_local (state.fn, NULL, 2412 state.int_type, "stack_depth"); 2413 state.x = 2414 gcc_jit_function_new_local (state.fn, NULL, 2415 state.int_type, "x"); 2416 state.y = 2417 gcc_jit_function_new_local (state.fn, NULL, 2418 state.int_type, "y"); 2419 2420@end example 2421@end quotation 2422 2423@node Populating the function,Verifying the control flow graph,Setting things up,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2424@anchor{intro/tutorial04 populating-the-function}@anchor{3c} 2425@subsection Populating the function 2426 2427 2428There’s some one-time initialization, and the API treats the first block 2429you create as the entrypoint of the function, so we need to create that 2430block first: 2431 2432@quotation 2433 2434@example 2435 state.initial_block = gcc_jit_function_new_block (state.fn, "initial"); 2436 2437@end example 2438@end quotation 2439 2440We can now create blocks for each of the operations. Most of these will 2441be consolidated into larger blocks when the optimizer runs. 2442 2443@quotation 2444 2445@example 2446 for (pc = 0; pc < fn->fn_num_ops; pc++) 2447 @{ 2448 char buf[16]; 2449 sprintf (buf, "instr%i", pc); 2450 state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); 2451 @} 2452 2453@end example 2454@end quotation 2455 2456Now that we have a block it can jump to when it’s done, we can populate 2457the initial block: 2458 2459@quotation 2460 2461@example 2462 2463 /* "stack_depth = 0;". */ 2464 gcc_jit_block_add_assignment ( 2465 state.initial_block, 2466 state.op_locs[0], 2467 state.stack_depth, 2468 gcc_jit_context_zero (state.ctxt, state.int_type)); 2469 2470 /* "PUSH (arg);". */ 2471 add_push (&state, 2472 state.initial_block, 2473 gcc_jit_param_as_rvalue (state.param_arg), 2474 state.op_locs[0]); 2475 2476 /* ...and jump to insn 0. */ 2477 gcc_jit_block_end_with_jump (state.initial_block, 2478 state.op_locs[0], 2479 state.op_blocks[0]); 2480 2481@end example 2482@end quotation 2483 2484We can now populate the blocks for the individual operations. We loop 2485through them, adding instructions to their blocks: 2486 2487@quotation 2488 2489@example 2490 for (pc = 0; pc < fn->fn_num_ops; pc++) 2491 @{ 2492 gcc_jit_location *loc = state.op_locs[pc]; 2493 2494 gcc_jit_block *block = state.op_blocks[pc]; 2495 gcc_jit_block *next_block = (pc < fn->fn_num_ops 2496 ? state.op_blocks[pc + 1] 2497 : NULL); 2498 2499 toyvm_op *op; 2500 op = &fn->fn_ops[pc]; 2501 2502@end example 2503@end quotation 2504 2505We’re going to have another big @code{switch} statement for implementing 2506the opcodes, this time for compiling them, rather than interpreting 2507them. It’s helpful to have macros for implementing push and pop, so that 2508we can make the @code{switch} statement that’s coming up look as much as 2509possible like the one above within the interpreter: 2510 2511@example 2512 2513#define X_EQUALS_POP()\ 2514 add_pop (&state, block, state.x, loc) 2515#define Y_EQUALS_POP()\ 2516 add_pop (&state, block, state.y, loc) 2517#define PUSH_RVALUE(RVALUE)\ 2518 add_push (&state, block, (RVALUE), loc) 2519#define PUSH_X()\ 2520 PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.x)) 2521#define PUSH_Y() \ 2522 PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.y)) 2523 2524@end example 2525 2526@cartouche 2527@quotation Note 2528A particularly clever implementation would have an @emph{identical} 2529@code{switch} statement shared by the interpreter and the compiler, with 2530some preprocessor “magic”. We’re not doing that here, for the sake 2531of simplicity. 2532@end quotation 2533@end cartouche 2534 2535When I first implemented this compiler, I accidentally missed an edit 2536when copying and pasting the @code{Y_EQUALS_POP} macro, so that popping the 2537stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y} 2538uninitialized. 2539 2540To track this kind of thing down, we can use 2541@ref{3d,,gcc_jit_block_add_comment()} to add descriptive comments 2542to the internal representation. This is invaluable when looking through 2543the generated IR for, say @code{factorial}: 2544 2545@quotation 2546 2547@example 2548 2549 gcc_jit_block_add_comment (block, loc, opcode_names[op->op_opcode]); 2550 2551@end example 2552@end quotation 2553 2554We can now write the big @code{switch} statement that implements the 2555individual opcodes, populating the relevant block with statements: 2556 2557@quotation 2558 2559@example 2560 2561 switch (op->op_opcode) 2562 @{ 2563 case DUP: 2564 X_EQUALS_POP (); 2565 PUSH_X (); 2566 PUSH_X (); 2567 break; 2568 2569 case ROT: 2570 Y_EQUALS_POP (); 2571 X_EQUALS_POP (); 2572 PUSH_Y (); 2573 PUSH_X (); 2574 break; 2575 2576 case BINARY_ADD: 2577 Y_EQUALS_POP (); 2578 X_EQUALS_POP (); 2579 PUSH_RVALUE ( 2580 gcc_jit_context_new_binary_op ( 2581 state.ctxt, 2582 loc, 2583 GCC_JIT_BINARY_OP_PLUS, 2584 state.int_type, 2585 gcc_jit_lvalue_as_rvalue (state.x), 2586 gcc_jit_lvalue_as_rvalue (state.y))); 2587 break; 2588 2589 case BINARY_SUBTRACT: 2590 Y_EQUALS_POP (); 2591 X_EQUALS_POP (); 2592 PUSH_RVALUE ( 2593 gcc_jit_context_new_binary_op ( 2594 state.ctxt, 2595 loc, 2596 GCC_JIT_BINARY_OP_MINUS, 2597 state.int_type, 2598 gcc_jit_lvalue_as_rvalue (state.x), 2599 gcc_jit_lvalue_as_rvalue (state.y))); 2600 break; 2601 2602 case BINARY_MULT: 2603 Y_EQUALS_POP (); 2604 X_EQUALS_POP (); 2605 PUSH_RVALUE ( 2606 gcc_jit_context_new_binary_op ( 2607 state.ctxt, 2608 loc, 2609 GCC_JIT_BINARY_OP_MULT, 2610 state.int_type, 2611 gcc_jit_lvalue_as_rvalue (state.x), 2612 gcc_jit_lvalue_as_rvalue (state.y))); 2613 break; 2614 2615 case BINARY_COMPARE_LT: 2616 Y_EQUALS_POP (); 2617 X_EQUALS_POP (); 2618 PUSH_RVALUE ( 2619 /* cast of bool to int */ 2620 gcc_jit_context_new_cast ( 2621 state.ctxt, 2622 loc, 2623 /* (x < y) as a bool */ 2624 gcc_jit_context_new_comparison ( 2625 state.ctxt, 2626 loc, 2627 GCC_JIT_COMPARISON_LT, 2628 gcc_jit_lvalue_as_rvalue (state.x), 2629 gcc_jit_lvalue_as_rvalue (state.y)), 2630 state.int_type)); 2631 break; 2632 2633 case RECURSE: 2634 @{ 2635 X_EQUALS_POP (); 2636 gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (state.x); 2637 PUSH_RVALUE ( 2638 gcc_jit_context_new_call ( 2639 state.ctxt, 2640 loc, 2641 state.fn, 2642 1, &arg)); 2643 break; 2644 @} 2645 2646 case RETURN: 2647 X_EQUALS_POP (); 2648 gcc_jit_block_end_with_return ( 2649 block, 2650 loc, 2651 gcc_jit_lvalue_as_rvalue (state.x)); 2652 break; 2653 2654 /* Ops taking an operand. */ 2655 case PUSH_CONST: 2656 PUSH_RVALUE ( 2657 gcc_jit_context_new_rvalue_from_int ( 2658 state.ctxt, 2659 state.int_type, 2660 op->op_operand)); 2661 break; 2662 2663 case JUMP_ABS_IF_TRUE: 2664 X_EQUALS_POP (); 2665 gcc_jit_block_end_with_conditional ( 2666 block, 2667 loc, 2668 /* "(bool)x". */ 2669 gcc_jit_context_new_cast ( 2670 state.ctxt, 2671 loc, 2672 gcc_jit_lvalue_as_rvalue (state.x), 2673 state.bool_type), 2674 state.op_blocks[op->op_operand], /* on_true */ 2675 next_block); /* on_false */ 2676 break; 2677 2678 default: 2679 assert(0); 2680 @} /* end of switch on opcode */ 2681 2682@end example 2683@end quotation 2684 2685Every block must be terminated, via a call to one of the 2686@code{gcc_jit_block_end_with_} entrypoints. This has been done for two 2687of the opcodes, but we need to do it for the other ones, by jumping 2688to the next block. 2689 2690@quotation 2691 2692@example 2693 if (op->op_opcode != JUMP_ABS_IF_TRUE 2694 && op->op_opcode != RETURN) 2695 gcc_jit_block_end_with_jump ( 2696 block, 2697 loc, 2698 next_block); 2699 2700@end example 2701@end quotation 2702 2703This is analogous to simply incrementing the program counter. 2704 2705@node Verifying the control flow graph,Compiling the context,Populating the function,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2706@anchor{intro/tutorial04 verifying-the-control-flow-graph}@anchor{3e} 2707@subsection Verifying the control flow graph 2708 2709 2710Having finished looping over the blocks, the context is complete. 2711 2712As before, we can verify that the control flow and statements are sane by 2713using @ref{33,,gcc_jit_function_dump_to_dot()}: 2714 2715@example 2716gcc_jit_function_dump_to_dot (state.fn, "/tmp/factorial.dot"); 2717@end example 2718 2719and viewing the result. Note how the label names, comments, and 2720variable names show up in the dump, to make it easier to spot 2721errors in our compiler. 2722 2723@quotation 2724 2725 2726@float Figure 2727 2728@image{libgccjit-figures/factorial1,,,image of a control flow graph,png} 2729 2730@end float 2731 2732@end quotation 2733 2734@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 2735@anchor{intro/tutorial04 compiling-the-context}@anchor{3f} 2736@subsection Compiling the context 2737 2738 2739Having finished looping over the blocks and populating them with 2740statements, the context is complete. 2741 2742We can now compile it, and extract machine code from the result: 2743 2744@quotation 2745@end quotation 2746 2747We can now run the result: 2748 2749@quotation 2750 2751@example 2752 toyvm_compiled_function *compiled_fn 2753 = toyvm_function_compile (fn); 2754 2755 toyvm_compiled_code code = compiled_fn->cf_code; 2756 printf ("compiler result: %d\n", 2757 code (atoi (argv[2]))); 2758 2759 gcc_jit_result_release (compiled_fn->cf_jit_result); 2760 free (compiled_fn); 2761 2762@end example 2763@end quotation 2764 2765@node Single-stepping through the generated code,Examining the generated code,Compiling the context,Tutorial part 4 Adding JIT-compilation to a toy interpreter 2766@anchor{intro/tutorial04 single-stepping-through-the-generated-code}@anchor{40} 2767@subsection Single-stepping through the generated code 2768 2769 2770It’s possible to debug the generated code. To do this we need to both: 2771 2772@quotation 2773 2774 2775@itemize * 2776 2777@item 2778Set up source code locations for our statements, so that we can 2779meaningfully step through the code. We did this above by 2780calling @ref{41,,gcc_jit_context_new_location()} and using the 2781results. 2782 2783@item 2784Enable the generation of debugging information, by setting 2785@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 2786@ref{8,,gcc_jit_context} via 2787@ref{1b,,gcc_jit_context_set_bool_option()}: 2788 2789@example 2790gcc_jit_context_set_bool_option ( 2791 ctxt, 2792 GCC_JIT_BOOL_OPTION_DEBUGINFO, 2793 1); 2794@end example 2795@end itemize 2796@end quotation 2797 2798Having done this, we can put a breakpoint on the generated function: 2799 2800@example 2801$ gdb --args ./toyvm factorial.toy 10 2802(gdb) break factorial 2803Function "factorial" not defined. 2804Make breakpoint pending on future shared library load? (y or [n]) y 2805Breakpoint 1 (factorial) pending. 2806(gdb) run 2807Breakpoint 1, factorial (arg=10) at factorial.toy:14 280814 DUP 2809@end example 2810 2811We’ve set up location information, which references @code{factorial.toy}. 2812This allows us to use e.g. @code{list} to see where we are in the script: 2813 2814@example 2815(gdb) list 28169 281710 # Initial state: 281811 # stack: [arg] 281912 282013 # 0: 282114 DUP 282215 # stack: [arg, arg] 282316 282417 # 1: 282518 PUSH_CONST 2 2826@end example 2827 2828and to step through the function, examining the data: 2829 2830@example 2831(gdb) n 283218 PUSH_CONST 2 2833(gdb) n 283422 BINARY_COMPARE_LT 2835(gdb) print stack 2836$5 = @{10, 10, 2, 0, -7152, 32767, 0, 0@} 2837(gdb) print stack_depth 2838$6 = 3 2839@end example 2840 2841You’ll see that the parts of the @code{stack} array that haven’t been 2842touched yet are uninitialized. 2843 2844@cartouche 2845@quotation Note 2846Turning on optimizations may lead to unpredictable results when 2847stepping through the generated code: the execution may appear to 2848“jump around” the source code. This is analogous to turning up the 2849optimization level in a regular compiler. 2850@end quotation 2851@end cartouche 2852 2853@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 2854@anchor{intro/tutorial04 examining-the-generated-code}@anchor{43} 2855@subsection Examining the generated code 2856 2857 2858How good is the optimized code? 2859 2860We can turn up optimizations, by calling 2861@ref{1e,,gcc_jit_context_set_int_option()} with 2862@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 2863 2864@example 2865gcc_jit_context_set_int_option ( 2866 ctxt, 2867 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2868 3); 2869@end example 2870 2871One of GCC’s internal representations is called “gimple”. A dump of the 2872initial gimple representation of the code can be seen by setting: 2873 2874@example 2875gcc_jit_context_set_bool_option (ctxt, 2876 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 2877 1); 2878@end example 2879 2880With optimization on and source locations displayed, this gives: 2881 2882@c We'll use "c" for gimple dumps 2883 2884@example 2885factorial (signed int arg) 2886@{ 2887 <unnamed type> D.80; 2888 signed int D.81; 2889 signed int D.82; 2890 signed int D.83; 2891 signed int D.84; 2892 signed int D.85; 2893 signed int y; 2894 signed int x; 2895 signed int stack_depth; 2896 signed int stack[8]; 2897 2898 try 2899 @{ 2900 initial: 2901 stack_depth = 0; 2902 stack[stack_depth] = arg; 2903 stack_depth = stack_depth + 1; 2904 goto instr0; 2905 instr0: 2906 /* DUP */: 2907 stack_depth = stack_depth + -1; 2908 x = stack[stack_depth]; 2909 stack[stack_depth] = x; 2910 stack_depth = stack_depth + 1; 2911 stack[stack_depth] = x; 2912 stack_depth = stack_depth + 1; 2913 goto instr1; 2914 instr1: 2915 /* PUSH_CONST */: 2916 stack[stack_depth] = 2; 2917 stack_depth = stack_depth + 1; 2918 goto instr2; 2919 2920 /* etc */ 2921@end example 2922 2923You can see the generated machine code in assembly form via: 2924 2925@example 2926gcc_jit_context_set_bool_option ( 2927 ctxt, 2928 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 2929 1); 2930result = gcc_jit_context_compile (ctxt); 2931@end example 2932 2933which shows that (on this x86_64 box) the compiler has unrolled the loop 2934and is using MMX instructions to perform several multiplications 2935simultaneously: 2936 2937@example 2938 .file "fake.c" 2939 .text 2940.Ltext0: 2941 .p2align 4,,15 2942 .globl factorial 2943 .type factorial, @@function 2944factorial: 2945.LFB0: 2946 .file 1 "factorial.toy" 2947 .loc 1 14 0 2948 .cfi_startproc 2949.LVL0: 2950.L2: 2951 .loc 1 26 0 2952 cmpl $1, %edi 2953 jle .L13 2954 leal -1(%rdi), %edx 2955 movl %edx, %ecx 2956 shrl $2, %ecx 2957 leal 0(,%rcx,4), %esi 2958 testl %esi, %esi 2959 je .L14 2960 cmpl $9, %edx 2961 jbe .L14 2962 leal -2(%rdi), %eax 2963 movl %eax, -16(%rsp) 2964 leal -3(%rdi), %eax 2965 movd -16(%rsp), %xmm0 2966 movl %edi, -16(%rsp) 2967 movl %eax, -12(%rsp) 2968 movd -16(%rsp), %xmm1 2969 xorl %eax, %eax 2970 movl %edx, -16(%rsp) 2971 movd -12(%rsp), %xmm4 2972 movd -16(%rsp), %xmm6 2973 punpckldq %xmm4, %xmm0 2974 movdqa .LC1(%rip), %xmm4 2975 punpckldq %xmm6, %xmm1 2976 punpcklqdq %xmm0, %xmm1 2977 movdqa .LC0(%rip), %xmm0 2978 jmp .L5 2979 # etc - edited for brevity 2980@end example 2981 2982This is clearly overkill for a function that will likely overflow the 2983@code{int} type before the vectorization is worthwhile - but then again, this 2984is a toy example. 2985 2986Turning down the optimization level to 2: 2987 2988@example 2989gcc_jit_context_set_int_option ( 2990 ctxt, 2991 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2992 3); 2993@end example 2994 2995yields this code, which is simple enough to quote in its entirety: 2996 2997@example 2998 .file "fake.c" 2999 .text 3000 .p2align 4,,15 3001 .globl factorial 3002 .type factorial, @@function 3003factorial: 3004.LFB0: 3005 .cfi_startproc 3006.L2: 3007 cmpl $1, %edi 3008 jle .L8 3009 movl $1, %edx 3010 jmp .L4 3011 .p2align 4,,10 3012 .p2align 3 3013.L6: 3014 movl %eax, %edi 3015.L4: 3016.L5: 3017 leal -1(%rdi), %eax 3018 imull %edi, %edx 3019 cmpl $1, %eax 3020 jne .L6 3021.L3: 3022.L7: 3023 imull %edx, %eax 3024 ret 3025.L8: 3026 movl %edi, %eax 3027 movl $1, %edx 3028 jmp .L7 3029 .cfi_endproc 3030.LFE0: 3031 .size factorial, .-factorial 3032 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%@{gcc_release@})" 3033 .section .note.GNU-stack,"",@@progbits 3034@end example 3035 3036Note that the stack pushing and popping have been eliminated, as has the 3037recursive call (in favor of an iteration). 3038 3039@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 3040@anchor{intro/tutorial04 putting-it-all-together}@anchor{44} 3041@subsection Putting it all together 3042 3043 3044The complete example can be seen in the source tree at 3045@code{gcc/jit/docs/examples/tut04-toyvm/toyvm.c} 3046 3047along with a Makefile and a couple of sample .toy scripts: 3048 3049@example 3050$ ls -al 3051drwxrwxr-x. 2 david david 4096 Sep 19 17:46 . 3052drwxrwxr-x. 3 david david 4096 Sep 19 15:26 .. 3053-rw-rw-r--. 1 david david 615 Sep 19 12:43 factorial.toy 3054-rw-rw-r--. 1 david david 834 Sep 19 13:08 fibonacci.toy 3055-rw-rw-r--. 1 david david 238 Sep 19 14:22 Makefile 3056-rw-rw-r--. 1 david david 16457 Sep 19 17:07 toyvm.c 3057 3058$ make toyvm 3059g++ -Wall -g -o toyvm toyvm.c -lgccjit 3060 3061$ ./toyvm factorial.toy 10 3062interpreter result: 3628800 3063compiler result: 3628800 3064 3065$ ./toyvm fibonacci.toy 10 3066interpreter result: 55 3067compiler result: 55 3068@end example 3069 3070@node Behind the curtain How does our code get optimized?,,Putting it all together,Tutorial part 4 Adding JIT-compilation to a toy interpreter 3071@anchor{intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{45} 3072@subsection Behind the curtain: How does our code get optimized? 3073 3074 3075Our example is done, but you may be wondering about exactly how the 3076compiler turned what we gave it into the machine code seen above. 3077 3078We can examine what the compiler is doing in detail by setting: 3079 3080@example 3081gcc_jit_context_set_bool_option (state.ctxt, 3082 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 3083 1); 3084gcc_jit_context_set_bool_option (state.ctxt, 3085 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 3086 1); 3087@end example 3088 3089This will dump detailed information about the compiler’s state to a 3090directory under @code{/tmp}, and keep it from being cleaned up. 3091 3092The precise names and their formats of these files is subject to change. 3093Higher optimization levels lead to more files. 3094Here’s what I saw (edited for brevity; there were almost 200 files): 3095 3096@example 3097intermediate files written to /tmp/libgccjit-KPQbGw 3098$ ls /tmp/libgccjit-KPQbGw/ 3099fake.c.000i.cgraph 3100fake.c.000i.type-inheritance 3101fake.c.004t.gimple 3102fake.c.007t.omplower 3103fake.c.008t.lower 3104fake.c.011t.eh 3105fake.c.012t.cfg 3106fake.c.014i.visibility 3107fake.c.015i.early_local_cleanups 3108fake.c.016t.ssa 3109# etc 3110@end example 3111 3112The gimple code is converted into Static Single Assignment form, 3113with annotations for use when generating the debuginfo: 3114 3115@example 3116$ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa 3117@end example 3118 3119@example 3120;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3121 3122factorial (signed int arg) 3123@{ 3124 signed int stack[8]; 3125 signed int stack_depth; 3126 signed int x; 3127 signed int y; 3128 <unnamed type> _20; 3129 signed int _21; 3130 signed int _38; 3131 signed int _44; 3132 signed int _51; 3133 signed int _56; 3134 3135initial: 3136 stack_depth_3 = 0; 3137 # DEBUG stack_depth => stack_depth_3 3138 stack[stack_depth_3] = arg_5(D); 3139 stack_depth_7 = stack_depth_3 + 1; 3140 # DEBUG stack_depth => stack_depth_7 3141 # DEBUG instr0 => NULL 3142 # DEBUG /* DUP */ => NULL 3143 stack_depth_8 = stack_depth_7 + -1; 3144 # DEBUG stack_depth => stack_depth_8 3145 x_9 = stack[stack_depth_8]; 3146 # DEBUG x => x_9 3147 stack[stack_depth_8] = x_9; 3148 stack_depth_11 = stack_depth_8 + 1; 3149 # DEBUG stack_depth => stack_depth_11 3150 stack[stack_depth_11] = x_9; 3151 stack_depth_13 = stack_depth_11 + 1; 3152 # DEBUG stack_depth => stack_depth_13 3153 # DEBUG instr1 => NULL 3154 # DEBUG /* PUSH_CONST */ => NULL 3155 stack[stack_depth_13] = 2; 3156 3157 /* etc; edited for brevity */ 3158@end example 3159 3160We can perhaps better see the code by turning off 3161@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to suppress all those @code{DEBUG} 3162statements, giving: 3163 3164@example 3165$ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa 3166@end example 3167 3168@example 3169;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3170 3171factorial (signed int arg) 3172@{ 3173 signed int stack[8]; 3174 signed int stack_depth; 3175 signed int x; 3176 signed int y; 3177 <unnamed type> _20; 3178 signed int _21; 3179 signed int _38; 3180 signed int _44; 3181 signed int _51; 3182 signed int _56; 3183 3184initial: 3185 stack_depth_3 = 0; 3186 stack[stack_depth_3] = arg_5(D); 3187 stack_depth_7 = stack_depth_3 + 1; 3188 stack_depth_8 = stack_depth_7 + -1; 3189 x_9 = stack[stack_depth_8]; 3190 stack[stack_depth_8] = x_9; 3191 stack_depth_11 = stack_depth_8 + 1; 3192 stack[stack_depth_11] = x_9; 3193 stack_depth_13 = stack_depth_11 + 1; 3194 stack[stack_depth_13] = 2; 3195 stack_depth_15 = stack_depth_13 + 1; 3196 stack_depth_16 = stack_depth_15 + -1; 3197 y_17 = stack[stack_depth_16]; 3198 stack_depth_18 = stack_depth_16 + -1; 3199 x_19 = stack[stack_depth_18]; 3200 _20 = x_19 < y_17; 3201 _21 = (signed int) _20; 3202 stack[stack_depth_18] = _21; 3203 stack_depth_23 = stack_depth_18 + 1; 3204 stack_depth_24 = stack_depth_23 + -1; 3205 x_25 = stack[stack_depth_24]; 3206 if (x_25 != 0) 3207 goto <bb 4> (instr9); 3208 else 3209 goto <bb 3> (instr4); 3210 3211instr4: 3212/* DUP */: 3213 stack_depth_26 = stack_depth_24 + -1; 3214 x_27 = stack[stack_depth_26]; 3215 stack[stack_depth_26] = x_27; 3216 stack_depth_29 = stack_depth_26 + 1; 3217 stack[stack_depth_29] = x_27; 3218 stack_depth_31 = stack_depth_29 + 1; 3219 stack[stack_depth_31] = 1; 3220 stack_depth_33 = stack_depth_31 + 1; 3221 stack_depth_34 = stack_depth_33 + -1; 3222 y_35 = stack[stack_depth_34]; 3223 stack_depth_36 = stack_depth_34 + -1; 3224 x_37 = stack[stack_depth_36]; 3225 _38 = x_37 - y_35; 3226 stack[stack_depth_36] = _38; 3227 stack_depth_40 = stack_depth_36 + 1; 3228 stack_depth_41 = stack_depth_40 + -1; 3229 x_42 = stack[stack_depth_41]; 3230 _44 = factorial (x_42); 3231 stack[stack_depth_41] = _44; 3232 stack_depth_46 = stack_depth_41 + 1; 3233 stack_depth_47 = stack_depth_46 + -1; 3234 y_48 = stack[stack_depth_47]; 3235 stack_depth_49 = stack_depth_47 + -1; 3236 x_50 = stack[stack_depth_49]; 3237 _51 = x_50 * y_48; 3238 stack[stack_depth_49] = _51; 3239 stack_depth_53 = stack_depth_49 + 1; 3240 3241 # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)> 3242instr9: 3243/* RETURN */: 3244 stack_depth_54 = stack_depth_1 + -1; 3245 x_55 = stack[stack_depth_54]; 3246 _56 = x_55; 3247 stack =@{v@} @{CLOBBER@}; 3248 return _56; 3249 3250@} 3251@end example 3252 3253Note in the above how all the @ref{28,,gcc_jit_block} instances we 3254created have been consolidated into just 3 blocks in GCC’s internal 3255representation: @code{initial}, @code{instr4} and @code{instr9}. 3256 3257@menu 3258* Optimizing away stack manipulation:: 3259* Elimination of tail recursion:: 3260 3261@end menu 3262 3263@node Optimizing away stack manipulation,Elimination of tail recursion,,Behind the curtain How does our code get optimized? 3264@anchor{intro/tutorial04 optimizing-away-stack-manipulation}@anchor{46} 3265@subsubsection Optimizing away stack manipulation 3266 3267 3268Recall our simple implementation of stack operations. Let’s examine 3269how the stack operations are optimized away. 3270 3271After a pass of constant-propagation, the depth of the stack at each 3272opcode can be determined at compile-time: 3273 3274@example 3275$ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1 3276@end example 3277 3278@example 3279;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3280 3281factorial (signed int arg) 3282@{ 3283 signed int stack[8]; 3284 signed int stack_depth; 3285 signed int x; 3286 signed int y; 3287 <unnamed type> _20; 3288 signed int _21; 3289 signed int _38; 3290 signed int _44; 3291 signed int _51; 3292 3293initial: 3294 stack[0] = arg_5(D); 3295 x_9 = stack[0]; 3296 stack[0] = x_9; 3297 stack[1] = x_9; 3298 stack[2] = 2; 3299 y_17 = stack[2]; 3300 x_19 = stack[1]; 3301 _20 = x_19 < y_17; 3302 _21 = (signed int) _20; 3303 stack[1] = _21; 3304 x_25 = stack[1]; 3305 if (x_25 != 0) 3306 goto <bb 4> (instr9); 3307 else 3308 goto <bb 3> (instr4); 3309 3310instr4: 3311/* DUP */: 3312 x_27 = stack[0]; 3313 stack[0] = x_27; 3314 stack[1] = x_27; 3315 stack[2] = 1; 3316 y_35 = stack[2]; 3317 x_37 = stack[1]; 3318 _38 = x_37 - y_35; 3319 stack[1] = _38; 3320 x_42 = stack[1]; 3321 _44 = factorial (x_42); 3322 stack[1] = _44; 3323 y_48 = stack[1]; 3324 x_50 = stack[0]; 3325 _51 = x_50 * y_48; 3326 stack[0] = _51; 3327 3328instr9: 3329/* RETURN */: 3330 x_55 = stack[0]; 3331 x_56 = x_55; 3332 stack =@{v@} @{CLOBBER@}; 3333 return x_56; 3334 3335@} 3336@end example 3337 3338Note how, in the above, all those @code{stack_depth} values are now just 3339constants: we’re accessing specific stack locations at each opcode. 3340 3341The “esra” pass (“Early Scalar Replacement of Aggregates”) breaks 3342out our “stack” array into individual elements: 3343 3344@example 3345$ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra 3346@end example 3347 3348@example 3349;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3350 3351Created a replacement for stack offset: 0, size: 32: stack$0 3352Created a replacement for stack offset: 32, size: 32: stack$1 3353Created a replacement for stack offset: 64, size: 32: stack$2 3354 3355Symbols to be put in SSA form 3356@{ D.89 D.90 D.91 @} 3357Incremental SSA update started at block: 0 3358Number of blocks in CFG: 5 3359Number of blocks to update: 4 ( 80%) 3360 3361 3362factorial (signed int arg) 3363@{ 3364 signed int stack$2; 3365 signed int stack$1; 3366 signed int stack$0; 3367 signed int stack[8]; 3368 signed int stack_depth; 3369 signed int x; 3370 signed int y; 3371 <unnamed type> _20; 3372 signed int _21; 3373 signed int _38; 3374 signed int _44; 3375 signed int _51; 3376 3377initial: 3378 stack$0_45 = arg_5(D); 3379 x_9 = stack$0_45; 3380 stack$0_39 = x_9; 3381 stack$1_32 = x_9; 3382 stack$2_30 = 2; 3383 y_17 = stack$2_30; 3384 x_19 = stack$1_32; 3385 _20 = x_19 < y_17; 3386 _21 = (signed int) _20; 3387 stack$1_28 = _21; 3388 x_25 = stack$1_28; 3389 if (x_25 != 0) 3390 goto <bb 4> (instr9); 3391 else 3392 goto <bb 3> (instr4); 3393 3394instr4: 3395/* DUP */: 3396 x_27 = stack$0_39; 3397 stack$0_22 = x_27; 3398 stack$1_14 = x_27; 3399 stack$2_12 = 1; 3400 y_35 = stack$2_12; 3401 x_37 = stack$1_14; 3402 _38 = x_37 - y_35; 3403 stack$1_10 = _38; 3404 x_42 = stack$1_10; 3405 _44 = factorial (x_42); 3406 stack$1_6 = _44; 3407 y_48 = stack$1_6; 3408 x_50 = stack$0_22; 3409 _51 = x_50 * y_48; 3410 stack$0_1 = _51; 3411 3412 # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)> 3413instr9: 3414/* RETURN */: 3415 x_55 = stack$0_52; 3416 x_56 = x_55; 3417 stack =@{v@} @{CLOBBER@}; 3418 return x_56; 3419 3420@} 3421@end example 3422 3423Hence at this point, all those pushes and pops of the stack are now 3424simply assignments to specific temporary variables. 3425 3426After some copy propagation, the stack manipulation has been completely 3427optimized away: 3428 3429@example 3430$ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1 3431@end example 3432 3433@example 3434;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3435 3436factorial (signed int arg) 3437@{ 3438 signed int stack$2; 3439 signed int stack$1; 3440 signed int stack$0; 3441 signed int stack[8]; 3442 signed int stack_depth; 3443 signed int x; 3444 signed int y; 3445 <unnamed type> _20; 3446 signed int _21; 3447 signed int _38; 3448 signed int _44; 3449 signed int _51; 3450 3451initial: 3452 stack$0_39 = arg_5(D); 3453 _20 = arg_5(D) <= 1; 3454 _21 = (signed int) _20; 3455 if (_21 != 0) 3456 goto <bb 4> (instr9); 3457 else 3458 goto <bb 3> (instr4); 3459 3460instr4: 3461/* DUP */: 3462 _38 = arg_5(D) + -1; 3463 _44 = factorial (_38); 3464 _51 = arg_5(D) * _44; 3465 stack$0_1 = _51; 3466 3467 # stack$0_52 = PHI <arg_5(D)(2), _51(3)> 3468instr9: 3469/* RETURN */: 3470 stack =@{v@} @{CLOBBER@}; 3471 return stack$0_52; 3472 3473@} 3474@end example 3475 3476Later on, another pass finally eliminated @code{stack_depth} local and the 3477unused parts of the @cite{stack`} array altogether: 3478 3479@example 3480$ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa 3481@end example 3482 3483@example 3484;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3485 3486Released 44 names, 314.29%, removed 44 holes 3487factorial (signed int arg) 3488@{ 3489 signed int stack$0; 3490 signed int mult_acc_1; 3491 <unnamed type> _5; 3492 signed int _6; 3493 signed int _7; 3494 signed int mul_tmp_10; 3495 signed int mult_acc_11; 3496 signed int mult_acc_13; 3497 3498 # arg_9 = PHI <arg_8(D)(0)> 3499 # mult_acc_13 = PHI <1(0)> 3500initial: 3501 3502 <bb 5>: 3503 # arg_4 = PHI <arg_9(2), _7(3)> 3504 # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)> 3505 _5 = arg_4 <= 1; 3506 _6 = (signed int) _5; 3507 if (_6 != 0) 3508 goto <bb 4> (instr9); 3509 else 3510 goto <bb 3> (instr4); 3511 3512instr4: 3513/* DUP */: 3514 _7 = arg_4 + -1; 3515 mult_acc_11 = mult_acc_1 * arg_4; 3516 goto <bb 5>; 3517 3518 # stack$0_12 = PHI <arg_4(5)> 3519instr9: 3520/* RETURN */: 3521 mul_tmp_10 = mult_acc_1 * stack$0_12; 3522 return mul_tmp_10; 3523 3524@} 3525@end example 3526 3527@node Elimination of tail recursion,,Optimizing away stack manipulation,Behind the curtain How does our code get optimized? 3528@anchor{intro/tutorial04 elimination-of-tail-recursion}@anchor{47} 3529@subsubsection Elimination of tail recursion 3530 3531 3532Another significant optimization is the detection that the call to 3533@code{factorial} is tail recursion, which can be eliminated in favor of 3534an iteration: 3535 3536@example 3537$ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1 3538@end example 3539 3540@example 3541;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 3542 3543 3544Symbols to be put in SSA form 3545@{ D.88 @} 3546Incremental SSA update started at block: 0 3547Number of blocks in CFG: 5 3548Number of blocks to update: 4 ( 80%) 3549 3550 3551factorial (signed int arg) 3552@{ 3553 signed int stack$2; 3554 signed int stack$1; 3555 signed int stack$0; 3556 signed int stack[8]; 3557 signed int stack_depth; 3558 signed int x; 3559 signed int y; 3560 signed int mult_acc_1; 3561 <unnamed type> _20; 3562 signed int _21; 3563 signed int _38; 3564 signed int mul_tmp_44; 3565 signed int mult_acc_51; 3566 3567 # arg_5 = PHI <arg_39(D)(0), _38(3)> 3568 # mult_acc_1 = PHI <1(0), mult_acc_51(3)> 3569initial: 3570 _20 = arg_5 <= 1; 3571 _21 = (signed int) _20; 3572 if (_21 != 0) 3573 goto <bb 4> (instr9); 3574 else 3575 goto <bb 3> (instr4); 3576 3577instr4: 3578/* DUP */: 3579 _38 = arg_5 + -1; 3580 mult_acc_51 = mult_acc_1 * arg_5; 3581 goto <bb 2> (initial); 3582 3583 # stack$0_52 = PHI <arg_5(2)> 3584instr9: 3585/* RETURN */: 3586 stack =@{v@} @{CLOBBER@}; 3587 mul_tmp_44 = mult_acc_1 * stack$0_52; 3588 return mul_tmp_44; 3589 3590@} 3591@end example 3592 3593@c Copyright (C) 2015-2021 Free Software Foundation, Inc. 3594@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 3595@c 3596@c This is free software: you can redistribute it and/or modify it 3597@c under the terms of the GNU General Public License as published by 3598@c the Free Software Foundation, either version 3 of the License, or 3599@c (at your option) any later version. 3600@c 3601@c This program is distributed in the hope that it will be useful, but 3602@c WITHOUT ANY WARRANTY; without even the implied warranty of 3603@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3604@c General Public License for more details. 3605@c 3606@c You should have received a copy of the GNU General Public License 3607@c along with this program. If not, see 3608@c <http://www.gnu.org/licenses/>. 3609 3610@node Tutorial part 5 Implementing an Ahead-of-Time compiler,,Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial 3611@anchor{intro/tutorial05 doc}@anchor{48}@anchor{intro/tutorial05 tutorial-part-5-implementing-an-ahead-of-time-compiler}@anchor{49} 3612@section Tutorial part 5: Implementing an Ahead-of-Time compiler 3613 3614 3615If you have a pre-existing language frontend that’s compatible with 3616libgccjit’s license, it’s possible to hook it up to libgccjit as a 3617backend. In the previous example we showed 3618how to do that for in-memory JIT-compilation, but libgccjit can also 3619compile code directly to a file, allowing you to implement a more 3620traditional ahead-of-time compiler (“JIT” is something of a misnomer 3621for this use-case). 3622 3623The essential difference is to compile the context using 3624@ref{4a,,gcc_jit_context_compile_to_file()} rather than 3625@ref{15,,gcc_jit_context_compile()}. 3626 3627@menu 3628* The “brainf” language:: 3629* Converting a brainf script to libgccjit IR:: 3630* Compiling a context to a file:: 3631* Other forms of ahead-of-time-compilation:: 3632 3633@end menu 3634 3635@node The “brainf” language,Converting a brainf script to libgccjit IR,,Tutorial part 5 Implementing an Ahead-of-Time compiler 3636@anchor{intro/tutorial05 the-brainf-language}@anchor{4b} 3637@subsection The “brainf” language 3638 3639 3640In this example we use libgccjit to construct an ahead-of-time compiler 3641for an esoteric programming language that we shall refer to as “brainf”. 3642 3643brainf scripts operate on an array of bytes, with a notional data pointer 3644within the array. 3645 3646brainf is hard for humans to read, but it’s trivial to write a parser for 3647it, as there is no lexing; just a stream of bytes. The operations are: 3648 3649 3650@multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} 3651@headitem 3652 3653Character 3654 3655@tab 3656 3657Meaning 3658 3659@item 3660 3661@code{>} 3662 3663@tab 3664 3665@code{idx += 1} 3666 3667@item 3668 3669@code{<} 3670 3671@tab 3672 3673@code{idx -= 1} 3674 3675@item 3676 3677@code{+} 3678 3679@tab 3680 3681@code{data[idx] += 1} 3682 3683@item 3684 3685@code{-} 3686 3687@tab 3688 3689@code{data[idx] -= 1} 3690 3691@item 3692 3693@code{.} 3694 3695@tab 3696 3697@code{output (data[idx])} 3698 3699@item 3700 3701@code{,} 3702 3703@tab 3704 3705@code{data[idx] = input ()} 3706 3707@item 3708 3709@code{[} 3710 3711@tab 3712 3713loop until @code{data[idx] == 0} 3714 3715@item 3716 3717@code{]} 3718 3719@tab 3720 3721end of loop 3722 3723@item 3724 3725Anything else 3726 3727@tab 3728 3729ignored 3730 3731@end multitable 3732 3733 3734Unlike the previous example, we’ll implement an ahead-of-time compiler, 3735which reads @code{.bf} scripts and outputs executables (though it would 3736be trivial to have it run them JIT-compiled in-process). 3737 3738Here’s what a simple @code{.bf} script looks like: 3739 3740@quotation 3741 3742@example 3743[ 3744 Emit the uppercase alphabet 3745] 3746 3747cell 0 = 26 3748++++++++++++++++++++++++++ 3749 3750cell 1 = 65 3751>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 3752 3753while cell#0 != 0 3754[ 3755 > 3756 . emit cell#1 3757 + increment cell@@1 3758 <- decrement cell@@0 3759] 3760@end example 3761@end quotation 3762 3763@cartouche 3764@quotation Note 3765This example makes use of whitespace and comments for legibility, but 3766could have been written as: 3767 3768@example 3769++++++++++++++++++++++++++ 3770>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 3771[>.+<-] 3772@end example 3773 3774It’s not a particularly useful language, except for providing 3775compiler-writers with a test case that’s easy to parse. The point 3776is that you can use @ref{4a,,gcc_jit_context_compile_to_file()} 3777to use libgccjit as a backend for a pre-existing language frontend 3778(provided that the pre-existing frontend is compatible with libgccjit’s 3779license). 3780@end quotation 3781@end cartouche 3782 3783@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 3784@anchor{intro/tutorial05 converting-a-brainf-script-to-libgccjit-ir}@anchor{4c} 3785@subsection Converting a brainf script to libgccjit IR 3786 3787 3788As before we write simple code to populate a @ref{8,,gcc_jit_context *}. 3789 3790@quotation 3791 3792@example 3793 3794typedef struct bf_compiler 3795@{ 3796 const char *filename; 3797 int line; 3798 int column; 3799 3800 gcc_jit_context *ctxt; 3801 3802 gcc_jit_type *void_type; 3803 gcc_jit_type *int_type; 3804 gcc_jit_type *byte_type; 3805 gcc_jit_type *array_type; 3806 3807 gcc_jit_function *func_getchar; 3808 gcc_jit_function *func_putchar; 3809 3810 gcc_jit_function *func; 3811 gcc_jit_block *curblock; 3812 3813 gcc_jit_rvalue *int_zero; 3814 gcc_jit_rvalue *int_one; 3815 gcc_jit_rvalue *byte_zero; 3816 gcc_jit_rvalue *byte_one; 3817 gcc_jit_lvalue *data_cells; 3818 gcc_jit_lvalue *idx; 3819 3820 int num_open_parens; 3821 gcc_jit_block *paren_test[MAX_OPEN_PARENS]; 3822 gcc_jit_block *paren_body[MAX_OPEN_PARENS]; 3823 gcc_jit_block *paren_after[MAX_OPEN_PARENS]; 3824 3825@} bf_compiler; 3826 3827/* Bail out, with a message on stderr. */ 3828 3829static void 3830fatal_error (bf_compiler *bfc, const char *msg) 3831@{ 3832 fprintf (stderr, 3833 "%s:%i:%i: %s", 3834 bfc->filename, bfc->line, bfc->column, msg); 3835 abort (); 3836@} 3837 3838/* Get "data_cells[idx]" as an lvalue. */ 3839 3840static gcc_jit_lvalue * 3841bf_get_current_data (bf_compiler *bfc, gcc_jit_location *loc) 3842@{ 3843 return gcc_jit_context_new_array_access ( 3844 bfc->ctxt, 3845 loc, 3846 gcc_jit_lvalue_as_rvalue (bfc->data_cells), 3847 gcc_jit_lvalue_as_rvalue (bfc->idx)); 3848@} 3849 3850/* Get "data_cells[idx] == 0" as a boolean rvalue. */ 3851 3852static gcc_jit_rvalue * 3853bf_current_data_is_zero (bf_compiler *bfc, gcc_jit_location *loc) 3854@{ 3855 return gcc_jit_context_new_comparison ( 3856 bfc->ctxt, 3857 loc, 3858 GCC_JIT_COMPARISON_EQ, 3859 gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)), 3860 bfc->byte_zero); 3861@} 3862 3863/* Compile one bf character. */ 3864 3865static void 3866bf_compile_char (bf_compiler *bfc, 3867 unsigned char ch) 3868@{ 3869 gcc_jit_location *loc = 3870 gcc_jit_context_new_location (bfc->ctxt, 3871 bfc->filename, 3872 bfc->line, 3873 bfc->column); 3874 3875 /* Turn this on to trace execution, by injecting putchar () 3876 of each source char. */ 3877 if (0) 3878 @{ 3879 gcc_jit_rvalue *arg = 3880 gcc_jit_context_new_rvalue_from_int ( 3881 bfc->ctxt, 3882 bfc->int_type, 3883 ch); 3884 gcc_jit_rvalue *call = 3885 gcc_jit_context_new_call (bfc->ctxt, 3886 loc, 3887 bfc->func_putchar, 3888 1, &arg); 3889 gcc_jit_block_add_eval (bfc->curblock, 3890 loc, 3891 call); 3892 @} 3893 3894 switch (ch) 3895 @{ 3896 case '>': 3897 gcc_jit_block_add_comment (bfc->curblock, 3898 loc, 3899 "'>': idx += 1;"); 3900 gcc_jit_block_add_assignment_op (bfc->curblock, 3901 loc, 3902 bfc->idx, 3903 GCC_JIT_BINARY_OP_PLUS, 3904 bfc->int_one); 3905 break; 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_MINUS, 3915 bfc->int_one); 3916 break; 3917 3918 case '+': 3919 gcc_jit_block_add_comment (bfc->curblock, 3920 loc, 3921 "'+': data[idx] += 1;"); 3922 gcc_jit_block_add_assignment_op (bfc->curblock, 3923 loc, 3924 bf_get_current_data (bfc, loc), 3925 GCC_JIT_BINARY_OP_PLUS, 3926 bfc->byte_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_MINUS, 3937 bfc->byte_one); 3938 break; 3939 3940 case '.': 3941 @{ 3942 gcc_jit_rvalue *arg = 3943 gcc_jit_context_new_cast ( 3944 bfc->ctxt, 3945 loc, 3946 gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)), 3947 bfc->int_type); 3948 gcc_jit_rvalue *call = 3949 gcc_jit_context_new_call (bfc->ctxt, 3950 loc, 3951 bfc->func_putchar, 3952 1, &arg); 3953 gcc_jit_block_add_comment (bfc->curblock, 3954 loc, 3955 "'.': putchar ((int)data[idx]);"); 3956 gcc_jit_block_add_eval (bfc->curblock, 3957 loc, 3958 call); 3959 @} 3960 break; 3961 3962 case ',': 3963 @{ 3964 gcc_jit_rvalue *call = 3965 gcc_jit_context_new_call (bfc->ctxt, 3966 loc, 3967 bfc->func_getchar, 3968 0, NULL); 3969 gcc_jit_block_add_comment ( 3970 bfc->curblock, 3971 loc, 3972 "',': data[idx] = (unsigned char)getchar ();"); 3973 gcc_jit_block_add_assignment (bfc->curblock, 3974 loc, 3975 bf_get_current_data (bfc, loc), 3976 gcc_jit_context_new_cast ( 3977 bfc->ctxt, 3978 loc, 3979 call, 3980 bfc->byte_type)); 3981 @} 3982 break; 3983 3984 case '[': 3985 @{ 3986 gcc_jit_block *loop_test = 3987 gcc_jit_function_new_block (bfc->func, NULL); 3988 gcc_jit_block *on_zero = 3989 gcc_jit_function_new_block (bfc->func, NULL); 3990 gcc_jit_block *on_non_zero = 3991 gcc_jit_function_new_block (bfc->func, NULL); 3992 3993 if (bfc->num_open_parens == MAX_OPEN_PARENS) 3994 fatal_error (bfc, "too many open parens"); 3995 3996 gcc_jit_block_end_with_jump ( 3997 bfc->curblock, 3998 loc, 3999 loop_test); 4000 4001 gcc_jit_block_add_comment ( 4002 loop_test, 4003 loc, 4004 "'['"); 4005 gcc_jit_block_end_with_conditional ( 4006 loop_test, 4007 loc, 4008 bf_current_data_is_zero (bfc, loc), 4009 on_zero, 4010 on_non_zero); 4011 bfc->paren_test[bfc->num_open_parens] = loop_test; 4012 bfc->paren_body[bfc->num_open_parens] = on_non_zero; 4013 bfc->paren_after[bfc->num_open_parens] = on_zero; 4014 bfc->num_open_parens += 1; 4015 bfc->curblock = on_non_zero; 4016 @} 4017 break; 4018 4019 case ']': 4020 @{ 4021 gcc_jit_block_add_comment ( 4022 bfc->curblock, 4023 loc, 4024 "']'"); 4025 4026 if (bfc->num_open_parens == 0) 4027 fatal_error (bfc, "mismatching parens"); 4028 bfc->num_open_parens -= 1; 4029 gcc_jit_block_end_with_jump ( 4030 bfc->curblock, 4031 loc, 4032 bfc->paren_test[bfc->num_open_parens]); 4033 bfc->curblock = bfc->paren_after[bfc->num_open_parens]; 4034 @} 4035 break; 4036 4037 case '\n': 4038 bfc->line +=1; 4039 bfc->column = 0; 4040 break; 4041 @} 4042 4043 if (ch != '\n') 4044 bfc->column += 1; 4045@} 4046 4047/* Compile the given .bf file into a gcc_jit_context, containing a 4048 single "main" function suitable for compiling into an executable. */ 4049 4050gcc_jit_context * 4051bf_compile (const char *filename) 4052@{ 4053 bf_compiler bfc; 4054 FILE *f_in; 4055 int ch; 4056 4057 memset (&bfc, 0, sizeof (bfc)); 4058 4059 bfc.filename = filename; 4060 f_in = fopen (filename, "r"); 4061 if (!f_in) 4062 fatal_error (&bfc, "unable to open file"); 4063 bfc.line = 1; 4064 4065 bfc.ctxt = gcc_jit_context_acquire (); 4066 4067 gcc_jit_context_set_int_option ( 4068 bfc.ctxt, 4069 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 4070 3); 4071 gcc_jit_context_set_bool_option ( 4072 bfc.ctxt, 4073 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 4074 0); 4075 gcc_jit_context_set_bool_option ( 4076 bfc.ctxt, 4077 GCC_JIT_BOOL_OPTION_DEBUGINFO, 4078 1); 4079 gcc_jit_context_set_bool_option ( 4080 bfc.ctxt, 4081 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 4082 0); 4083 gcc_jit_context_set_bool_option ( 4084 bfc.ctxt, 4085 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 4086 0); 4087 4088 bfc.void_type = 4089 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_VOID); 4090 bfc.int_type = 4091 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_INT); 4092 bfc.byte_type = 4093 gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR); 4094 bfc.array_type = 4095 gcc_jit_context_new_array_type (bfc.ctxt, 4096 NULL, 4097 bfc.byte_type, 4098 30000); 4099 4100 bfc.func_getchar = 4101 gcc_jit_context_new_function (bfc.ctxt, NULL, 4102 GCC_JIT_FUNCTION_IMPORTED, 4103 bfc.int_type, 4104 "getchar", 4105 0, NULL, 4106 0); 4107 4108 gcc_jit_param *param_c = 4109 gcc_jit_context_new_param (bfc.ctxt, NULL, bfc.int_type, "c"); 4110 bfc.func_putchar = 4111 gcc_jit_context_new_function (bfc.ctxt, NULL, 4112 GCC_JIT_FUNCTION_IMPORTED, 4113 bfc.void_type, 4114 "putchar", 4115 1, ¶m_c, 4116 0); 4117 4118 bfc.func = make_main (bfc.ctxt); 4119 bfc.curblock = 4120 gcc_jit_function_new_block (bfc.func, "initial"); 4121 bfc.int_zero = gcc_jit_context_zero (bfc.ctxt, bfc.int_type); 4122 bfc.int_one = gcc_jit_context_one (bfc.ctxt, bfc.int_type); 4123 bfc.byte_zero = gcc_jit_context_zero (bfc.ctxt, bfc.byte_type); 4124 bfc.byte_one = gcc_jit_context_one (bfc.ctxt, bfc.byte_type); 4125 4126 bfc.data_cells = 4127 gcc_jit_context_new_global (bfc.ctxt, NULL, 4128 GCC_JIT_GLOBAL_INTERNAL, 4129 bfc.array_type, 4130 "data_cells"); 4131 bfc.idx = 4132 gcc_jit_function_new_local (bfc.func, NULL, 4133 bfc.int_type, 4134 "idx"); 4135 4136 gcc_jit_block_add_comment (bfc.curblock, 4137 NULL, 4138 "idx = 0;"); 4139 gcc_jit_block_add_assignment (bfc.curblock, 4140 NULL, 4141 bfc.idx, 4142 bfc.int_zero); 4143 4144 bfc.num_open_parens = 0; 4145 4146 while ( EOF != (ch = fgetc (f_in))) 4147 bf_compile_char (&bfc, (unsigned char)ch); 4148 4149 gcc_jit_block_end_with_return (bfc.curblock, NULL, bfc.int_zero); 4150 4151 fclose (f_in); 4152 4153 return bfc.ctxt; 4154@} 4155 4156@end example 4157@end quotation 4158 4159@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 4160@anchor{intro/tutorial05 compiling-a-context-to-a-file}@anchor{4d} 4161@subsection Compiling a context to a file 4162 4163 4164Unlike the previous tutorial, this time we’ll compile the context 4165directly to an executable, using @ref{4a,,gcc_jit_context_compile_to_file()}: 4166 4167@example 4168gcc_jit_context_compile_to_file (ctxt, 4169 GCC_JIT_OUTPUT_KIND_EXECUTABLE, 4170 output_file); 4171@end example 4172 4173Here’s the top-level of the compiler, which is what actually calls into 4174@ref{4a,,gcc_jit_context_compile_to_file()}: 4175 4176@quotation 4177 4178@example 4179 4180int 4181main (int argc, char **argv) 4182@{ 4183 const char *input_file; 4184 const char *output_file; 4185 gcc_jit_context *ctxt; 4186 const char *err; 4187 4188 if (argc != 3) 4189 @{ 4190 fprintf (stderr, "%s: INPUT_FILE OUTPUT_FILE\n", argv[0]); 4191 return 1; 4192 @} 4193 4194 input_file = argv[1]; 4195 output_file = argv[2]; 4196 ctxt = bf_compile (input_file); 4197 4198 gcc_jit_context_compile_to_file (ctxt, 4199 GCC_JIT_OUTPUT_KIND_EXECUTABLE, 4200 output_file); 4201 4202 err = gcc_jit_context_get_first_error (ctxt); 4203 4204 if (err) 4205 @{ 4206 gcc_jit_context_release (ctxt); 4207 return 1; 4208 @} 4209 4210 gcc_jit_context_release (ctxt); 4211 return 0; 4212@} 4213 4214@end example 4215@end quotation 4216 4217Note how once the context is populated you could trivially instead compile 4218it to memory using @ref{15,,gcc_jit_context_compile()} and run it in-process 4219as in the previous tutorial. 4220 4221To create an executable, we need to export a @code{main} function. Here’s 4222how to create one from the JIT API: 4223 4224@quotation 4225 4226@example 4227 4228/* Make "main" function: 4229 int 4230 main (int argc, char **argv) 4231 @{ 4232 ... 4233 @} 4234*/ 4235static gcc_jit_function * 4236make_main (gcc_jit_context *ctxt) 4237@{ 4238 gcc_jit_type *int_type = 4239 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 4240 gcc_jit_param *param_argc = 4241 gcc_jit_context_new_param (ctxt, NULL, int_type, "argc"); 4242 gcc_jit_type *char_ptr_ptr_type = 4243 gcc_jit_type_get_pointer ( 4244 gcc_jit_type_get_pointer ( 4245 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR))); 4246 gcc_jit_param *param_argv = 4247 gcc_jit_context_new_param (ctxt, NULL, char_ptr_ptr_type, "argv"); 4248 gcc_jit_param *params[2] = @{param_argc, param_argv@}; 4249 gcc_jit_function *func_main = 4250 gcc_jit_context_new_function (ctxt, NULL, 4251 GCC_JIT_FUNCTION_EXPORTED, 4252 int_type, 4253 "main", 4254 2, params, 4255 0); 4256 return func_main; 4257@} 4258 4259@end example 4260@end quotation 4261 4262@cartouche 4263@quotation Note 4264The above implementation ignores @code{argc} and @code{argv}, but you could 4265make use of them by exposing @code{param_argc} and @code{param_argv} to the 4266caller. 4267@end quotation 4268@end cartouche 4269 4270Upon compiling this C code, we obtain a bf-to-machine-code compiler; 4271let’s call it @code{bfc}: 4272 4273@example 4274$ gcc \ 4275 tut05-bf.c \ 4276 -o bfc \ 4277 -lgccjit 4278@end example 4279 4280We can now use @code{bfc} to compile .bf files into machine code executables: 4281 4282@example 4283$ ./bfc \ 4284 emit-alphabet.bf \ 4285 a.out 4286@end example 4287 4288which we can run directly: 4289 4290@example 4291$ ./a.out 4292ABCDEFGHIJKLMNOPQRSTUVWXYZ 4293@end example 4294 4295Success! 4296 4297We can also inspect the generated executable using standard tools: 4298 4299@example 4300$ objdump -d a.out |less 4301@end example 4302 4303which shows that libgccjit has managed to optimize the function 4304somewhat (for example, the runs of 26 and 65 increment operations 4305have become integer constants 0x1a and 0x41): 4306 4307@example 43080000000000400620 <main>: 4309 400620: 80 3d 39 0a 20 00 00 cmpb $0x0,0x200a39(%rip) # 601060 <data 4310 400627: 74 07 je 400630 <main 4311 400629: eb fe jmp 400629 <main+0x9> 4312 40062b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4313 400630: 48 83 ec 08 sub $0x8,%rsp 4314 400634: 0f b6 05 26 0a 20 00 movzbl 0x200a26(%rip),%eax # 601061 <data_cells+0x1> 4315 40063b: c6 05 1e 0a 20 00 1a movb $0x1a,0x200a1e(%rip) # 601060 <data_cells> 4316 400642: 8d 78 41 lea 0x41(%rax),%edi 4317 400645: 40 88 3d 15 0a 20 00 mov %dil,0x200a15(%rip) # 601061 <data_cells+0x1> 4318 40064c: 0f 1f 40 00 nopl 0x0(%rax) 4319 400650: 40 0f b6 ff movzbl %dil,%edi 4320 400654: e8 87 fe ff ff callq 4004e0 <putchar@@plt> 4321 400659: 0f b6 05 01 0a 20 00 movzbl 0x200a01(%rip),%eax # 601061 <data_cells+0x1> 4322 400660: 80 2d f9 09 20 00 01 subb $0x1,0x2009f9(%rip) # 601060 <data_cells> 4323 400667: 8d 78 01 lea 0x1(%rax),%edi 4324 40066a: 40 88 3d f0 09 20 00 mov %dil,0x2009f0(%rip) # 601061 <data_cells+0x1> 4325 400671: 75 dd jne 400650 <main+0x30> 4326 400673: 31 c0 xor %eax,%eax 4327 400675: 48 83 c4 08 add $0x8,%rsp 4328 400679: c3 retq 4329 40067a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 4330@end example 4331 4332We also set up debugging information (via 4333@ref{41,,gcc_jit_context_new_location()} and 4334@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO}), so it’s possible to use @code{gdb} 4335to singlestep through the generated binary and inspect the internal 4336state @code{idx} and @code{data_cells}: 4337 4338@example 4339(gdb) break main 4340Breakpoint 1 at 0x400790 4341(gdb) run 4342Starting program: a.out 4343 4344Breakpoint 1, 0x0000000000400790 in main (argc=1, argv=0x7fffffffe448) 4345(gdb) stepi 43460x0000000000400797 in main (argc=1, argv=0x7fffffffe448) 4347(gdb) stepi 43480x00000000004007a0 in main (argc=1, argv=0x7fffffffe448) 4349(gdb) stepi 43509 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4351(gdb) list 43524 43535 cell 0 = 26 43546 ++++++++++++++++++++++++++ 43557 43568 cell 1 = 65 43579 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 435810 435911 while cell#0 != 0 436012 [ 436113 > 4362(gdb) n 43636 ++++++++++++++++++++++++++ 4364(gdb) n 43659 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 4366(gdb) p idx 4367$1 = 1 4368(gdb) p data_cells 4369$2 = "\032", '\000' <repeats 29998 times> 4370(gdb) p data_cells[0] 4371$3 = 26 '\032' 4372(gdb) p data_cells[1] 4373$4 = 0 '\000' 4374(gdb) list 43754 43765 cell 0 = 26 43776 ++++++++++++++++++++++++++ 43787 43798 cell 1 = 65 43809 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++< 438110 438211 while cell#0 != 0 438312 [ 438413 > 4385@end example 4386 4387@node Other forms of ahead-of-time-compilation,,Compiling a context to a file,Tutorial part 5 Implementing an Ahead-of-Time compiler 4388@anchor{intro/tutorial05 other-forms-of-ahead-of-time-compilation}@anchor{4e} 4389@subsection Other forms of ahead-of-time-compilation 4390 4391 4392The above demonstrates compiling a @ref{8,,gcc_jit_context *} directly 4393to an executable. It’s also possible to compile it to an object file, 4394and to a dynamic library. See the documentation of 4395@ref{4a,,gcc_jit_context_compile_to_file()} for more information. 4396 4397@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 4398@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 4399@c 4400@c This is free software: you can redistribute it and/or modify it 4401@c under the terms of the GNU General Public License as published by 4402@c the Free Software Foundation, either version 3 of the License, or 4403@c (at your option) any later version. 4404@c 4405@c This program is distributed in the hope that it will be useful, but 4406@c WITHOUT ANY WARRANTY; without even the implied warranty of 4407@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4408@c General Public License for more details. 4409@c 4410@c You should have received a copy of the GNU General Public License 4411@c along with this program. If not, see 4412@c <http://www.gnu.org/licenses/>. 4413 4414@node Topic Reference,C++ bindings for libgccjit,Tutorial,Top 4415@anchor{topics/index doc}@anchor{4f}@anchor{topics/index topic-reference}@anchor{50} 4416@chapter Topic Reference 4417 4418 4419@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 4420@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 4421@c 4422@c This is free software: you can redistribute it and/or modify it 4423@c under the terms of the GNU General Public License as published by 4424@c the Free Software Foundation, either version 3 of the License, or 4425@c (at your option) any later version. 4426@c 4427@c This program is distributed in the hope that it will be useful, but 4428@c WITHOUT ANY WARRANTY; without even the implied warranty of 4429@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4430@c General Public License for more details. 4431@c 4432@c You should have received a copy of the GNU General Public License 4433@c along with this program. If not, see 4434@c <http://www.gnu.org/licenses/>. 4435 4436@menu 4437* Compilation contexts:: 4438* Objects:: 4439* Types:: 4440* Expressions:: 4441* Creating and using functions:: 4442* Function pointers: Function pointers<2>. 4443* Source Locations:: 4444* Compiling a context:: 4445* ABI and API compatibility:: 4446* Performance:: 4447* Using Assembly Language with libgccjit:: 4448 4449@end menu 4450 4451@node Compilation contexts,Objects,,Topic Reference 4452@anchor{topics/contexts doc}@anchor{51}@anchor{topics/contexts compilation-contexts}@anchor{52} 4453@section Compilation contexts 4454 4455 4456@geindex gcc_jit_context (C type) 4457@anchor{topics/contexts c gcc_jit_context}@anchor{8} 4458@deffn {C Type} gcc_jit_context 4459@end deffn 4460 4461The top-level of the API is the @ref{8,,gcc_jit_context} type. 4462 4463A @ref{8,,gcc_jit_context} instance encapsulates the state of a 4464compilation. 4465 4466You can set up options on it, and add types, functions and code. 4467Invoking @ref{15,,gcc_jit_context_compile()} on it gives you a 4468@ref{16,,gcc_jit_result}. 4469 4470@menu 4471* Lifetime-management:: 4472* Thread-safety:: 4473* Error-handling: Error-handling<2>. 4474* Debugging:: 4475* Options: Options<2>. 4476 4477@end menu 4478 4479@node Lifetime-management,Thread-safety,,Compilation contexts 4480@anchor{topics/contexts lifetime-management}@anchor{53} 4481@subsection Lifetime-management 4482 4483 4484Contexts are the unit of lifetime-management within the API: objects 4485have their lifetime bounded by the context they are created within, and 4486cleanup of such objects is done for you when the context is released. 4487 4488@geindex gcc_jit_context_acquire (C function) 4489@anchor{topics/contexts c gcc_jit_context_acquire}@anchor{9} 4490@deffn {C Function} gcc_jit_context *gcc_jit_context_acquire (void) 4491 4492This function acquires a new @ref{8,,gcc_jit_context *} instance, 4493which is independent of any others that may be present within this 4494process. 4495@end deffn 4496 4497@geindex gcc_jit_context_release (C function) 4498@anchor{topics/contexts c gcc_jit_context_release}@anchor{c} 4499@deffn {C Function} void gcc_jit_context_release (gcc_jit_context@w{ }*ctxt) 4500 4501This function releases all resources associated with the given context. 4502Both the context itself and all of its @ref{e,,gcc_jit_object *} 4503instances are cleaned up. It should be called exactly once on a given 4504context. 4505 4506It is invalid to use the context or any of its “contextual” objects 4507after calling this. 4508 4509@example 4510gcc_jit_context_release (ctxt); 4511@end example 4512@end deffn 4513 4514@geindex gcc_jit_context_new_child_context (C function) 4515@anchor{topics/contexts c gcc_jit_context_new_child_context}@anchor{54} 4516@deffn {C Function} gcc_jit_context * gcc_jit_context_new_child_context (gcc_jit_context@w{ }*parent_ctxt) 4517 4518Given an existing JIT context, create a child context. 4519 4520The child inherits a copy of all option-settings from the parent. 4521 4522The child can reference objects created within the parent, but not 4523vice-versa. 4524 4525The lifetime of the child context must be bounded by that of the 4526parent: you should release a child context before releasing the parent 4527context. 4528 4529If you use a function from a parent context within a child context, 4530you have to compile the parent context before you can compile the 4531child context, and the gcc_jit_result of the parent context must 4532outlive the gcc_jit_result of the child context. 4533 4534This allows caching of shared initializations. For example, you could 4535create types and declarations of global functions in a parent context 4536once within a process, and then create child contexts whenever a 4537function or loop becomes hot. Each such child context can be used for 4538JIT-compiling just one function or loop, but can reference types 4539and helper functions created within the parent context. 4540 4541Contexts can be arbitrarily nested, provided the above rules are 4542followed, but it’s probably not worth going above 2 or 3 levels, and 4543there will likely be a performance hit for such nesting. 4544@end deffn 4545 4546@node Thread-safety,Error-handling<2>,Lifetime-management,Compilation contexts 4547@anchor{topics/contexts thread-safety}@anchor{55} 4548@subsection Thread-safety 4549 4550 4551Instances of @ref{8,,gcc_jit_context *} created via 4552@ref{9,,gcc_jit_context_acquire()} are independent from each other: 4553only one thread may use a given context at once, but multiple threads 4554could each have their own contexts without needing locks. 4555 4556Contexts created via @ref{54,,gcc_jit_context_new_child_context()} are 4557related to their parent context. They can be partitioned by their 4558ultimate ancestor into independent “family trees”. Only one thread 4559within a process may use a given “family tree” of such contexts at once, 4560and if you’re using multiple threads you should provide your own locking 4561around entire such context partitions. 4562 4563@node Error-handling<2>,Debugging,Thread-safety,Compilation contexts 4564@anchor{topics/contexts error-handling}@anchor{19}@anchor{topics/contexts id1}@anchor{56} 4565@subsection Error-handling 4566 4567 4568Various kinds of errors are possible when using the API, such as 4569mismatched types in an assignment. You can only compile and get code from 4570a context if no errors occur. 4571 4572Errors are printed on stderr and can be queried using 4573@ref{57,,gcc_jit_context_get_first_error()}. 4574 4575They typically contain the name of the API entrypoint where the error 4576occurred, and pertinent information on the problem: 4577 4578@example 4579./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *) 4580@end example 4581 4582In general, if an error occurs when using an API entrypoint, the 4583entrypoint returns NULL. You don’t have to check everywhere for NULL 4584results, since the API handles a NULL being passed in for any 4585argument by issuing another error. This typically leads to a cascade of 4586followup error messages, but is safe (albeit verbose). The first error 4587message is usually the one to pay attention to, since it is likely to 4588be responsible for all of the rest: 4589 4590@geindex gcc_jit_context_get_first_error (C function) 4591@anchor{topics/contexts c gcc_jit_context_get_first_error}@anchor{57} 4592@deffn {C Function} const char * gcc_jit_context_get_first_error (gcc_jit_context@w{ }*ctxt) 4593 4594Returns the first error message that occurred on the context. 4595 4596The returned string is valid for the rest of the lifetime of the 4597context. 4598 4599If no errors occurred, this will be NULL. 4600@end deffn 4601 4602If you are wrapping the C API for a higher-level language that supports 4603exception-handling, you may instead be interested in the last error that 4604occurred on the context, so that you can embed this in an exception: 4605 4606@geindex gcc_jit_context_get_last_error (C function) 4607@anchor{topics/contexts c gcc_jit_context_get_last_error}@anchor{58} 4608@deffn {C Function} const char * gcc_jit_context_get_last_error (gcc_jit_context@w{ }*ctxt) 4609 4610Returns the last error message that occurred on the context. 4611 4612If no errors occurred, this will be NULL. 4613 4614If non-NULL, the returned string is only guaranteed to be valid until 4615the next call to libgccjit relating to this context. 4616@end deffn 4617 4618@node Debugging,Options<2>,Error-handling<2>,Compilation contexts 4619@anchor{topics/contexts debugging}@anchor{59} 4620@subsection Debugging 4621 4622 4623@geindex gcc_jit_context_dump_to_file (C function) 4624@anchor{topics/contexts c gcc_jit_context_dump_to_file}@anchor{5a} 4625@deffn {C Function} void gcc_jit_context_dump_to_file (gcc_jit_context@w{ }*ctxt, const char@w{ }*path, int@w{ }update_locations) 4626 4627To help with debugging: dump a C-like representation to the given path, 4628describing what’s been set up on the context. 4629 4630If “update_locations” is true, then also set up @ref{3b,,gcc_jit_location} 4631information throughout the context, pointing at the dump file as if it 4632were a source file. This may be of use in conjunction with 4633@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to allow stepping through the 4634code in a debugger. 4635@end deffn 4636 4637@geindex gcc_jit_context_set_logfile (C function) 4638@anchor{topics/contexts c gcc_jit_context_set_logfile}@anchor{5b} 4639@deffn {C Function} void gcc_jit_context_set_logfile (gcc_jit_context@w{ }*ctxt, FILE@w{ }*logfile, int@w{ }flags, int@w{ }verbosity) 4640 4641To help with debugging; enable ongoing logging of the context’s 4642activity to the given file. 4643 4644For example, the following will enable logging to stderr. 4645 4646@example 4647gcc_jit_context_set_logfile (ctxt, stderr, 0, 0); 4648@end example 4649 4650Examples of information logged include: 4651 4652 4653@itemize * 4654 4655@item 4656API calls 4657 4658@item 4659the various steps involved within compilation 4660 4661@item 4662activity on any @ref{16,,gcc_jit_result} instances created by 4663the context 4664 4665@item 4666activity within any child contexts 4667@end itemize 4668 4669An example of a log can be seen @ref{5c,,here}, 4670though the precise format and kinds of information logged is subject 4671to change. 4672 4673The caller remains responsible for closing @cite{logfile}, and it must not 4674be closed until all users are released. In particular, note that 4675child contexts and @ref{16,,gcc_jit_result} instances created by 4676the context will use the logfile. 4677 4678There may a performance cost for logging. 4679 4680You can turn off logging on @cite{ctxt} by passing @cite{NULL} for @cite{logfile}. 4681Doing so only affects the context; it does not affect child contexts 4682or @ref{16,,gcc_jit_result} instances already created by 4683the context. 4684 4685The parameters “flags” and “verbosity” are reserved for future 4686expansion, and must be zero for now. 4687@end deffn 4688 4689To contrast the above: @ref{5a,,gcc_jit_context_dump_to_file()} dumps the 4690current state of a context to the given path, whereas 4691@ref{5b,,gcc_jit_context_set_logfile()} enables on-going logging of 4692future activies on a context to the given @cite{FILE *}. 4693 4694@geindex gcc_jit_context_dump_reproducer_to_file (C function) 4695@anchor{topics/contexts c gcc_jit_context_dump_reproducer_to_file}@anchor{5d} 4696@deffn {C Function} void gcc_jit_context_dump_reproducer_to_file (gcc_jit_context@w{ }*ctxt, const char@w{ }*path) 4697 4698Write C source code into @cite{path} that can be compiled into a 4699self-contained executable (i.e. with libgccjit as the only dependency). 4700The generated code will attempt to replay the API calls that have been 4701made into the given context. 4702 4703This may be useful when debugging the library or client code, for 4704reducing a complicated recipe for reproducing a bug into a simpler 4705form. For example, consider client code that parses some source file 4706into some internal representation, and then walks this IR, calling into 4707libgccjit. If this encounters a bug, a call to 4708@cite{gcc_jit_context_dump_reproducer_to_file} will write out C code for 4709a much simpler executable that performs the equivalent calls into 4710libgccjit, without needing the client code and its data. 4711 4712Typically you need to supply @code{-Wno-unused-variable} when 4713compiling the generated file (since the result of each API call is 4714assigned to a unique variable within the generated C source, and not 4715all are necessarily then used). 4716@end deffn 4717 4718@geindex gcc_jit_context_enable_dump (C function) 4719@anchor{topics/contexts c gcc_jit_context_enable_dump}@anchor{5e} 4720@deffn {C Function} void gcc_jit_context_enable_dump (gcc_jit_context@w{ }*ctxt, const char@w{ }*dumpname, char@w{ }**out_ptr) 4721 4722Enable the dumping of a specific set of internal state from the 4723compilation, capturing the result in-memory as a buffer. 4724 4725Parameter “dumpname” corresponds to the equivalent gcc command-line 4726option, without the “-fdump-” prefix. 4727For example, to get the equivalent of @code{-fdump-tree-vrp1}, 4728supply @code{"tree-vrp1"}: 4729 4730@example 4731static char *dump_vrp1; 4732 4733void 4734create_code (gcc_jit_context *ctxt) 4735@{ 4736 gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1); 4737 /* (other API calls omitted for brevity) */ 4738@} 4739@end example 4740 4741The context directly stores the dumpname as a @code{(const char *)}, so 4742the passed string must outlive the context. 4743 4744@ref{15,,gcc_jit_context_compile()} will capture the dump as a 4745dynamically-allocated buffer, writing it to @code{*out_ptr}. 4746 4747The caller becomes responsible for calling: 4748 4749@example 4750free (*out_ptr) 4751@end example 4752 4753each time that @ref{15,,gcc_jit_context_compile()} is called. 4754@code{*out_ptr} will be written to, either with the address of a buffer, 4755or with @code{NULL} if an error occurred. 4756 4757@cartouche 4758@quotation Warning 4759This API entrypoint is likely to be less stable than the others. 4760In particular, both the precise dumpnames, and the format and content 4761of the dumps are subject to change. 4762 4763It exists primarily for writing the library’s own test suite. 4764@end quotation 4765@end cartouche 4766@end deffn 4767 4768@node Options<2>,,Debugging,Compilation contexts 4769@anchor{topics/contexts options}@anchor{5f} 4770@subsection Options 4771 4772 4773Options present in the initial release of libgccjit were handled using 4774enums, whereas those added subsequently have their own per-option API 4775entrypoints. 4776 4777Adding entrypoints for each new option means that client code that use 4778the new options can be identified directly from binary metadata, which 4779would not be possible if we instead extended the various 4780@code{enum gcc_jit_*_option}. 4781 4782@menu 4783* String Options:: 4784* Boolean options:: 4785* Integer options:: 4786* Additional command-line options:: 4787 4788@end menu 4789 4790@node String Options,Boolean options,,Options<2> 4791@anchor{topics/contexts string-options}@anchor{60} 4792@subsubsection String Options 4793 4794 4795@geindex gcc_jit_context_set_str_option (C function) 4796@anchor{topics/contexts c gcc_jit_context_set_str_option}@anchor{61} 4797@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) 4798 4799Set a string option of the context. 4800 4801@geindex gcc_jit_str_option (C type) 4802@anchor{topics/contexts c gcc_jit_str_option}@anchor{62} 4803@deffn {C Type} enum gcc_jit_str_option 4804@end deffn 4805 4806The parameter @code{value} can be NULL. If non-NULL, the call takes a 4807copy of the underlying string, so it is valid to pass in a pointer to 4808an on-stack buffer. 4809 4810There is just one string option specified this way: 4811 4812@geindex GCC_JIT_STR_OPTION_PROGNAME (C macro) 4813@anchor{topics/contexts c GCC_JIT_STR_OPTION_PROGNAME}@anchor{63} 4814@deffn {C Macro} GCC_JIT_STR_OPTION_PROGNAME 4815 4816The name of the program, for use as a prefix when printing error 4817messages to stderr. If @cite{NULL}, or default, “libgccjit.so” is used. 4818@end deffn 4819@end deffn 4820 4821@node Boolean options,Integer options,String Options,Options<2> 4822@anchor{topics/contexts boolean-options}@anchor{64} 4823@subsubsection Boolean options 4824 4825 4826@geindex gcc_jit_context_set_bool_option (C function) 4827@anchor{topics/contexts c gcc_jit_context_set_bool_option}@anchor{1b} 4828@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) 4829 4830Set a boolean option of the context. 4831Zero is “false” (the default), non-zero is “true”. 4832 4833@geindex gcc_jit_bool_option (C type) 4834@anchor{topics/contexts c gcc_jit_bool_option}@anchor{65} 4835@deffn {C Type} enum gcc_jit_bool_option 4836@end deffn 4837 4838@geindex GCC_JIT_BOOL_OPTION_DEBUGINFO (C macro) 4839@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DEBUGINFO}@anchor{42} 4840@deffn {C Macro} GCC_JIT_BOOL_OPTION_DEBUGINFO 4841 4842If true, @ref{15,,gcc_jit_context_compile()} will attempt to do the right 4843thing so that if you attach a debugger to the process, it will 4844be able to inspect variables and step through your code. 4845 4846Note that you can’t step through code unless you set up source 4847location information for the code (by creating and passing in 4848@ref{3b,,gcc_jit_location} instances). 4849@end deffn 4850 4851@geindex GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE (C macro) 4852@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE}@anchor{66} 4853@deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE 4854 4855If true, @ref{15,,gcc_jit_context_compile()} will dump its initial 4856“tree” representation of your code to stderr (before any 4857optimizations). 4858 4859Here’s some sample output (from the @cite{square} example): 4860 4861@example 4862<statement_list 0x7f4875a62cc0 4863 type <void_type 0x7f4875a64bd0 VOID 4864 align 8 symtab 0 alias set -1 canonical type 0x7f4875a64bd0 4865 pointer_to_this <pointer_type 0x7f4875a64c78>> 4866 side-effects head 0x7f4875a761e0 tail 0x7f4875a761f8 stmts 0x7f4875a62d20 0x7f4875a62d00 4867 4868 stmt <label_expr 0x7f4875a62d20 type <void_type 0x7f4875a64bd0> 4869 side-effects 4870 arg 0 <label_decl 0x7f4875a79080 entry type <void_type 0x7f4875a64bd0> 4871 VOID file (null) line 0 col 0 4872 align 1 context <function_decl 0x7f4875a77500 square>>> 4873 stmt <return_expr 0x7f4875a62d00 4874 type <integer_type 0x7f4875a645e8 public SI 4875 size <integer_cst 0x7f4875a623a0 constant 32> 4876 unit size <integer_cst 0x7f4875a623c0 constant 4> 4877 align 32 symtab 0 alias set -1 canonical type 0x7f4875a645e8 precision 32 min <integer_cst 0x7f4875a62340 -2147483648> max <integer_cst 0x7f4875a62360 2147483647> 4878 pointer_to_this <pointer_type 0x7f4875a6b348>> 4879 side-effects 4880 arg 0 <modify_expr 0x7f4875a72a78 type <integer_type 0x7f4875a645e8> 4881 side-effects arg 0 <result_decl 0x7f4875a7a000 D.54> 4882 arg 1 <mult_expr 0x7f4875a72a50 type <integer_type 0x7f4875a645e8> 4883 arg 0 <parm_decl 0x7f4875a79000 i> arg 1 <parm_decl 0x7f4875a79000 i>>>>> 4884@end example 4885@end deffn 4886 4887@geindex GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE (C macro) 4888@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}@anchor{1c} 4889@deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE 4890 4891If true, @ref{15,,gcc_jit_context_compile()} will dump the “gimple” 4892representation of your code to stderr, before any optimizations 4893are performed. The dump resembles C code: 4894 4895@example 4896square (signed int i) 4897@{ 4898 signed int D.56; 4899 4900 entry: 4901 D.56 = i * i; 4902 return D.56; 4903@} 4904@end example 4905@end deffn 4906 4907@geindex GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE (C macro) 4908@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE}@anchor{1d} 4909@deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE 4910 4911If true, @ref{15,,gcc_jit_context_compile()} will dump the final 4912generated code to stderr, in the form of assembly language: 4913 4914@example 4915 .file "fake.c" 4916 .text 4917 .globl square 4918 .type square, @@function 4919square: 4920.LFB0: 4921 .cfi_startproc 4922 pushq %rbp 4923 .cfi_def_cfa_offset 16 4924 .cfi_offset 6, -16 4925 movq %rsp, %rbp 4926 .cfi_def_cfa_register 6 4927 movl %edi, -4(%rbp) 4928.L2: 4929 movl -4(%rbp), %eax 4930 imull -4(%rbp), %eax 4931 popq %rbp 4932 .cfi_def_cfa 7, 8 4933 ret 4934 .cfi_endproc 4935.LFE0: 4936 .size square, .-square 4937 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.1-%@{gcc_release@})" 4938 .section .note.GNU-stack,"",@@progbits 4939@end example 4940@end deffn 4941 4942@geindex GCC_JIT_BOOL_OPTION_DUMP_SUMMARY (C macro) 4943@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_SUMMARY}@anchor{67} 4944@deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_SUMMARY 4945 4946If true, @ref{15,,gcc_jit_context_compile()} will print information to stderr 4947on the actions it is performing. 4948@end deffn 4949 4950@geindex GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING (C macro) 4951@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING}@anchor{68} 4952@deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING 4953 4954If true, @ref{15,,gcc_jit_context_compile()} will dump copious 4955amount of information on what it’s doing to various 4956files within a temporary directory. Use 4957@ref{69,,GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES} (see below) to 4958see the results. The files are intended to be human-readable, 4959but the exact files and their formats are subject to change. 4960@end deffn 4961 4962@geindex GCC_JIT_BOOL_OPTION_SELFCHECK_GC (C macro) 4963@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_SELFCHECK_GC}@anchor{6a} 4964@deffn {C Macro} GCC_JIT_BOOL_OPTION_SELFCHECK_GC 4965 4966If true, libgccjit will aggressively run its garbage collector, to 4967shake out bugs (greatly slowing down the compile). This is likely 4968to only be of interest to developers @emph{of} the library. It is 4969used when running the selftest suite. 4970@end deffn 4971 4972@geindex GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (C macro) 4973@anchor{topics/contexts c GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES}@anchor{69} 4974@deffn {C Macro} GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES 4975 4976If true, the @ref{8,,gcc_jit_context} will not clean up intermediate files 4977written to the filesystem, and will display their location on stderr. 4978@end deffn 4979@end deffn 4980 4981@geindex gcc_jit_context_set_bool_allow_unreachable_blocks (C function) 4982@anchor{topics/contexts c gcc_jit_context_set_bool_allow_unreachable_blocks}@anchor{6b} 4983@deffn {C Function} void gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context@w{ }*ctxt, int@w{ }bool_value) 4984 4985By default, libgccjit will issue an error about unreachable blocks 4986within a function. 4987 4988This entrypoint can be used to disable that error. 4989 4990This entrypoint was added in @ref{6c,,LIBGCCJIT_ABI_2}; you can test for 4991its presence using 4992 4993@example 4994#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks 4995@end example 4996@end deffn 4997 4998@geindex gcc_jit_context_set_bool_use_external_driver (C function) 4999@anchor{topics/contexts c gcc_jit_context_set_bool_use_external_driver}@anchor{6d} 5000@deffn {C Function} void gcc_jit_context_set_bool_use_external_driver (gcc_jit_context@w{ }*ctxt, int@w{ }bool_value) 5001 5002libgccjit internally generates assembler, and uses “driver” code 5003for converting it to other formats (e.g. shared libraries). 5004 5005By default, libgccjit will use an embedded copy of the driver 5006code. 5007 5008This option can be used to instead invoke an external driver executable 5009as a subprocess. 5010 5011This entrypoint was added in @ref{6e,,LIBGCCJIT_ABI_5}; you can test for 5012its presence using 5013 5014@example 5015#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver 5016@end example 5017@end deffn 5018 5019@node Integer options,Additional command-line options,Boolean options,Options<2> 5020@anchor{topics/contexts integer-options}@anchor{6f} 5021@subsubsection Integer options 5022 5023 5024@geindex gcc_jit_context_set_int_option (C function) 5025@anchor{topics/contexts c gcc_jit_context_set_int_option}@anchor{1e} 5026@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) 5027 5028Set an integer option of the context. 5029 5030@geindex gcc_jit_int_option (C type) 5031@anchor{topics/contexts c gcc_jit_int_option}@anchor{70} 5032@deffn {C Type} enum gcc_jit_int_option 5033@end deffn 5034 5035There is just one integer option specified this way: 5036 5037@geindex GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL (C macro) 5038@anchor{topics/contexts c GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}@anchor{1f} 5039@deffn {C Macro} GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL 5040 5041How much to optimize the code. 5042 5043Valid values are 0-3, corresponding to GCC’s command-line options 5044-O0 through -O3. 5045 5046The default value is 0 (unoptimized). 5047@end deffn 5048@end deffn 5049 5050@node Additional command-line options,,Integer options,Options<2> 5051@anchor{topics/contexts additional-command-line-options}@anchor{71} 5052@subsubsection Additional command-line options 5053 5054 5055@geindex gcc_jit_context_add_command_line_option (C function) 5056@anchor{topics/contexts c gcc_jit_context_add_command_line_option}@anchor{72} 5057@deffn {C Function} void gcc_jit_context_add_command_line_option (gcc_jit_context@w{ }*ctxt, const char@w{ }*optname) 5058 5059Add an arbitrary gcc command-line option to the context, for use 5060by @ref{15,,gcc_jit_context_compile()} and 5061@ref{4a,,gcc_jit_context_compile_to_file()}. 5062 5063The parameter @code{optname} must be non-NULL. The underlying buffer is 5064copied, so that it does not need to outlive the call. 5065 5066Extra options added by @cite{gcc_jit_context_add_command_line_option} are 5067applied @emph{after} the regular options above, potentially overriding them. 5068Options from parent contexts are inherited by child contexts; options 5069from the parent are applied @emph{before} those from the child. 5070 5071For example: 5072 5073@example 5074gcc_jit_context_add_command_line_option (ctxt, "-ffast-math"); 5075gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm"); 5076@end example 5077 5078Note that only some options are likely to be meaningful; there is no 5079“frontend” within libgccjit, so typically only those affecting 5080optimization and code-generation are likely to be useful. 5081 5082This entrypoint was added in @ref{73,,LIBGCCJIT_ABI_1}; you can test for 5083its presence using 5084 5085@example 5086#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option 5087@end example 5088@end deffn 5089 5090@geindex gcc_jit_context_add_driver_option (C function) 5091@anchor{topics/contexts c gcc_jit_context_add_driver_option}@anchor{74} 5092@deffn {C Function} void gcc_jit_context_add_driver_option (gcc_jit_context@w{ }*ctxt, const char@w{ }*optname) 5093 5094Add an arbitrary gcc driver option to the context, for use by 5095@ref{15,,gcc_jit_context_compile()} and 5096@ref{4a,,gcc_jit_context_compile_to_file()}. 5097 5098The parameter @code{optname} must be non-NULL. The underlying buffer is 5099copied, so that it does not need to outlive the call. 5100 5101Extra options added by @cite{gcc_jit_context_add_driver_option} are 5102applied @emph{after} all other options potentially overriding them. 5103Options from parent contexts are inherited by child contexts; options 5104from the parent are applied @emph{before} those from the child. 5105 5106For example: 5107 5108@example 5109gcc_jit_context_add_driver_option (ctxt, "-lm"); 5110gcc_jit_context_add_driver_option (ctxt, "-fuse-linker-plugin"); 5111@end example 5112 5113Note that only some options are likely to be meaningful; there is no 5114“frontend” within libgccjit, so typically only those affecting 5115assembler and linker are likely to be useful. 5116 5117This entrypoint was added in @ref{75,,LIBGCCJIT_ABI_11}; you can test for 5118its presence using 5119 5120@example 5121#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_driver_option 5122@end example 5123@end deffn 5124 5125@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 5126@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 5127@c 5128@c This is free software: you can redistribute it and/or modify it 5129@c under the terms of the GNU General Public License as published by 5130@c the Free Software Foundation, either version 3 of the License, or 5131@c (at your option) any later version. 5132@c 5133@c This program is distributed in the hope that it will be useful, but 5134@c WITHOUT ANY WARRANTY; without even the implied warranty of 5135@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5136@c General Public License for more details. 5137@c 5138@c You should have received a copy of the GNU General Public License 5139@c along with this program. If not, see 5140@c <http://www.gnu.org/licenses/>. 5141 5142@node Objects,Types,Compilation contexts,Topic Reference 5143@anchor{topics/objects doc}@anchor{76}@anchor{topics/objects objects}@anchor{77} 5144@section Objects 5145 5146 5147@geindex gcc_jit_object (C type) 5148@anchor{topics/objects c gcc_jit_object}@anchor{e} 5149@deffn {C Type} gcc_jit_object 5150@end deffn 5151 5152Almost every entity in the API (with the exception of 5153@ref{8,,gcc_jit_context *} and @ref{16,,gcc_jit_result *}) is a 5154“contextual” object, a @ref{e,,gcc_jit_object *} 5155 5156A JIT object: 5157 5158@quotation 5159 5160 5161@itemize * 5162 5163@item 5164is associated with a @ref{8,,gcc_jit_context *}. 5165 5166@item 5167is automatically cleaned up for you when its context is released so 5168you don’t need to manually track and cleanup all objects, just the 5169contexts. 5170@end itemize 5171@end quotation 5172 5173Although the API is C-based, there is a form of class hierarchy, which 5174looks like this: 5175 5176@example 5177+- gcc_jit_object 5178 +- gcc_jit_location 5179 +- gcc_jit_type 5180 +- gcc_jit_struct 5181 +- gcc_jit_field 5182 +- gcc_jit_function 5183 +- gcc_jit_block 5184 +- gcc_jit_rvalue 5185 +- gcc_jit_lvalue 5186 +- gcc_jit_param 5187 +- gcc_jit_case 5188 +- gcc_jit_extended_asm 5189@end example 5190 5191There are casting methods for upcasting from subclasses to parent classes. 5192For example, @ref{d,,gcc_jit_type_as_object()}: 5193 5194@example 5195gcc_jit_object *obj = gcc_jit_type_as_object (int_type); 5196@end example 5197 5198The object “base class” has the following operations: 5199 5200@geindex gcc_jit_object_get_context (C function) 5201@anchor{topics/objects c gcc_jit_object_get_context}@anchor{78} 5202@deffn {C Function} gcc_jit_context *gcc_jit_object_get_context (gcc_jit_object@w{ }*obj) 5203 5204Which context is “obj” within? 5205@end deffn 5206 5207@geindex gcc_jit_object_get_debug_string (C function) 5208@anchor{topics/objects c gcc_jit_object_get_debug_string}@anchor{f} 5209@deffn {C Function} const char *gcc_jit_object_get_debug_string (gcc_jit_object@w{ }*obj) 5210 5211Generate a human-readable description for the given object. 5212 5213For example, 5214 5215@example 5216printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj)); 5217@end example 5218 5219might give this text on stdout: 5220 5221@example 5222obj: 4.0 * (float)i 5223@end example 5224 5225@cartouche 5226@quotation Note 5227If you call this on an object, the @cite{const char *} buffer is allocated 5228and generated on the first call for that object, and the buffer will 5229have the same lifetime as the object i.e. it will exist until the 5230object’s context is released. 5231@end quotation 5232@end cartouche 5233@end deffn 5234 5235@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 5236@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 5237@c 5238@c This is free software: you can redistribute it and/or modify it 5239@c under the terms of the GNU General Public License as published by 5240@c the Free Software Foundation, either version 3 of the License, or 5241@c (at your option) any later version. 5242@c 5243@c This program is distributed in the hope that it will be useful, but 5244@c WITHOUT ANY WARRANTY; without even the implied warranty of 5245@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5246@c General Public License for more details. 5247@c 5248@c You should have received a copy of the GNU General Public License 5249@c along with this program. If not, see 5250@c <http://www.gnu.org/licenses/>. 5251 5252@node Types,Expressions,Objects,Topic Reference 5253@anchor{topics/types doc}@anchor{79}@anchor{topics/types types}@anchor{7a} 5254@section Types 5255 5256 5257@geindex gcc_jit_type (C type) 5258@anchor{topics/types c gcc_jit_type}@anchor{a} 5259@deffn {C Type} gcc_jit_type 5260 5261gcc_jit_type represents a type within the library. 5262@end deffn 5263 5264@geindex gcc_jit_type_as_object (C function) 5265@anchor{topics/types c gcc_jit_type_as_object}@anchor{d} 5266@deffn {C Function} gcc_jit_object *gcc_jit_type_as_object (gcc_jit_type@w{ }*type) 5267 5268Upcast a type to an object. 5269@end deffn 5270 5271Types can be created in several ways: 5272 5273 5274@itemize * 5275 5276@item 5277fundamental types can be accessed using 5278@ref{b,,gcc_jit_context_get_type()}: 5279 5280@example 5281gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 5282@end example 5283 5284See @ref{b,,gcc_jit_context_get_type()} for the available types. 5285 5286@item 5287derived types can be accessed by using functions such as 5288@ref{7b,,gcc_jit_type_get_pointer()} and @ref{7c,,gcc_jit_type_get_const()}: 5289 5290@example 5291gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type)); 5292gcc_jit_type *int_const_star = gcc_jit_type_get_const (gcc_jit_type_get_pointer (int_type)); 5293@end example 5294 5295@item 5296by creating structures (see below). 5297@end itemize 5298 5299@menu 5300* Standard types:: 5301* Pointers@comma{} const@comma{} and volatile: Pointers const and volatile. 5302* Vector types:: 5303* Structures and unions:: 5304* Function pointer types:: 5305 5306@end menu 5307 5308@node Standard types,Pointers const and volatile,,Types 5309@anchor{topics/types standard-types}@anchor{7d} 5310@subsection Standard types 5311 5312 5313@geindex gcc_jit_context_get_type (C function) 5314@anchor{topics/types c gcc_jit_context_get_type}@anchor{b} 5315@deffn {C Function} gcc_jit_type *gcc_jit_context_get_type (gcc_jit_context@w{ }*ctxt, enum gcc_jit_types@w{ }type_) 5316 5317Access a specific type. The available types are: 5318 5319 5320@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} 5321@headitem 5322 5323@cite{enum gcc_jit_types} value 5324 5325@tab 5326 5327Meaning 5328 5329@item 5330 5331@code{GCC_JIT_TYPE_VOID} 5332 5333@tab 5334 5335C’s @code{void} type. 5336 5337@item 5338 5339@code{GCC_JIT_TYPE_VOID_PTR} 5340 5341@tab 5342 5343C’s @code{void *}. 5344 5345@item 5346 5347@code{GCC_JIT_TYPE_BOOL} 5348 5349@tab 5350 5351C++’s @code{bool} type; also C99’s 5352@code{_Bool} type, aka @code{bool} if 5353using stdbool.h. 5354 5355@item 5356 5357@code{GCC_JIT_TYPE_CHAR} 5358 5359@tab 5360 5361C’s @code{char} (of some signedness) 5362 5363@item 5364 5365@code{GCC_JIT_TYPE_SIGNED_CHAR} 5366 5367@tab 5368 5369C’s @code{signed char} 5370 5371@item 5372 5373@code{GCC_JIT_TYPE_UNSIGNED_CHAR} 5374 5375@tab 5376 5377C’s @code{unsigned char} 5378 5379@item 5380 5381@code{GCC_JIT_TYPE_SHORT} 5382 5383@tab 5384 5385C’s @code{short} (signed) 5386 5387@item 5388 5389@code{GCC_JIT_TYPE_UNSIGNED_SHORT} 5390 5391@tab 5392 5393C’s @code{unsigned short} 5394 5395@item 5396 5397@code{GCC_JIT_TYPE_INT} 5398 5399@tab 5400 5401C’s @code{int} (signed) 5402 5403@item 5404 5405@code{GCC_JIT_TYPE_UNSIGNED_INT} 5406 5407@tab 5408 5409C’s @code{unsigned int} 5410 5411@item 5412 5413@code{GCC_JIT_TYPE_LONG} 5414 5415@tab 5416 5417C’s @code{long} (signed) 5418 5419@item 5420 5421@code{GCC_JIT_TYPE_UNSIGNED_LONG} 5422 5423@tab 5424 5425C’s @code{unsigned long} 5426 5427@item 5428 5429@code{GCC_JIT_TYPE_LONG_LONG} 5430 5431@tab 5432 5433C99’s @code{long long} (signed) 5434 5435@item 5436 5437@code{GCC_JIT_TYPE_UNSIGNED_LONG_LONG} 5438 5439@tab 5440 5441C99’s @code{unsigned long long} 5442 5443@item 5444 5445@code{GCC_JIT_TYPE_FLOAT} 5446 5447@tab 5448 5449@item 5450 5451@code{GCC_JIT_TYPE_DOUBLE} 5452 5453@tab 5454 5455@item 5456 5457@code{GCC_JIT_TYPE_LONG_DOUBLE} 5458 5459@tab 5460 5461@item 5462 5463@code{GCC_JIT_TYPE_CONST_CHAR_PTR} 5464 5465@tab 5466 5467C type: @code{(const char *)} 5468 5469@item 5470 5471@code{GCC_JIT_TYPE_SIZE_T} 5472 5473@tab 5474 5475C’s @code{size_t} type 5476 5477@item 5478 5479@code{GCC_JIT_TYPE_FILE_PTR} 5480 5481@tab 5482 5483C type: @code{(FILE *)} 5484 5485@item 5486 5487@code{GCC_JIT_TYPE_COMPLEX_FLOAT} 5488 5489@tab 5490 5491C99’s @code{_Complex float} 5492 5493@item 5494 5495@code{GCC_JIT_TYPE_COMPLEX_DOUBLE} 5496 5497@tab 5498 5499C99’s @code{_Complex double} 5500 5501@item 5502 5503@code{GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE} 5504 5505@tab 5506 5507C99’s @code{_Complex long double} 5508 5509@end multitable 5510 5511@end deffn 5512 5513@geindex gcc_jit_context_get_int_type (C function) 5514@anchor{topics/types c gcc_jit_context_get_int_type}@anchor{7e} 5515@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) 5516 5517Access the integer type of the given size. 5518@end deffn 5519 5520@node Pointers const and volatile,Vector types,Standard types,Types 5521@anchor{topics/types pointers-const-and-volatile}@anchor{7f} 5522@subsection Pointers, @cite{const}, and @cite{volatile} 5523 5524 5525@geindex gcc_jit_type_get_pointer (C function) 5526@anchor{topics/types c gcc_jit_type_get_pointer}@anchor{7b} 5527@deffn {C Function} gcc_jit_type *gcc_jit_type_get_pointer (gcc_jit_type@w{ }*type) 5528 5529Given type “T”, get type “T*”. 5530@end deffn 5531 5532@geindex gcc_jit_type_get_const (C function) 5533@anchor{topics/types c gcc_jit_type_get_const}@anchor{7c} 5534@deffn {C Function} gcc_jit_type *gcc_jit_type_get_const (gcc_jit_type@w{ }*type) 5535 5536Given type “T”, get type “const T”. 5537@end deffn 5538 5539@geindex gcc_jit_type_get_volatile (C function) 5540@anchor{topics/types c gcc_jit_type_get_volatile}@anchor{80} 5541@deffn {C Function} gcc_jit_type *gcc_jit_type_get_volatile (gcc_jit_type@w{ }*type) 5542 5543Given type “T”, get type “volatile T”. 5544@end deffn 5545 5546@geindex gcc_jit_context_new_array_type (C function) 5547@anchor{topics/types c gcc_jit_context_new_array_type}@anchor{81} 5548@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) 5549 5550Given non-@cite{void} type “T”, get type “T[N]” (for a constant N). 5551@end deffn 5552 5553@geindex gcc_jit_type_get_aligned (C function) 5554@anchor{topics/types c gcc_jit_type_get_aligned}@anchor{82} 5555@deffn {C Function} gcc_jit_type * gcc_jit_type_get_aligned (gcc_jit_type@w{ }*type, size_t@w{ }alignment_in_bytes) 5556 5557Given non-@cite{void} type “T”, get type: 5558 5559@example 5560T __attribute__ ((aligned (ALIGNMENT_IN_BYTES))) 5561@end example 5562 5563The alignment must be a power of two. 5564 5565This entrypoint was added in @ref{83,,LIBGCCJIT_ABI_7}; you can test for 5566its presence using 5567 5568@example 5569#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned 5570@end example 5571@end deffn 5572 5573@node Vector types,Structures and unions,Pointers const and volatile,Types 5574@anchor{topics/types vector-types}@anchor{84} 5575@subsection Vector types 5576 5577 5578@geindex gcc_jit_type_get_vector (C function) 5579@anchor{topics/types c gcc_jit_type_get_vector}@anchor{85} 5580@deffn {C Function} gcc_jit_type * gcc_jit_type_get_vector (gcc_jit_type@w{ }*type, size_t@w{ }num_units) 5581 5582Given type “T”, get type: 5583 5584@example 5585T __attribute__ ((vector_size (sizeof(T) * num_units)) 5586@end example 5587 5588T must be integral or floating point; num_units must be a power of two. 5589 5590This can be used to construct a vector type in which operations 5591are applied element-wise. The compiler will automatically 5592use SIMD instructions where possible. See: 5593@indicateurl{https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html} 5594 5595For example, assuming 4-byte @code{ints}, then: 5596 5597@example 5598typedef int v4si __attribute__ ((vector_size (16))); 5599@end example 5600 5601can be obtained using: 5602 5603@example 5604gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, 5605 GCC_JIT_TYPE_INT); 5606gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4); 5607@end example 5608 5609This API entrypoint was added in @ref{86,,LIBGCCJIT_ABI_8}; you can test 5610for its presence using 5611 5612@example 5613#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector 5614@end example 5615 5616Vector rvalues can be generated using 5617@ref{87,,gcc_jit_context_new_rvalue_from_vector()}. 5618@end deffn 5619 5620@node Structures and unions,Function pointer types,Vector types,Types 5621@anchor{topics/types structures-and-unions}@anchor{88} 5622@subsection Structures and unions 5623 5624 5625@geindex gcc_jit_struct (C type) 5626@anchor{topics/types c gcc_jit_struct}@anchor{89} 5627@deffn {C Type} gcc_jit_struct 5628@end deffn 5629 5630A compound type analagous to a C @cite{struct}. 5631 5632@geindex gcc_jit_field (C type) 5633@anchor{topics/types c gcc_jit_field}@anchor{8a} 5634@deffn {C Type} gcc_jit_field 5635@end deffn 5636 5637A field within a @ref{89,,gcc_jit_struct}. 5638 5639You can model C @cite{struct} types by creating @ref{89,,gcc_jit_struct *} and 5640@ref{8a,,gcc_jit_field} instances, in either order: 5641 5642 5643@itemize * 5644 5645@item 5646by creating the fields, then the structure. For example, to model: 5647 5648@example 5649struct coord @{double x; double y; @}; 5650@end example 5651 5652you could call: 5653 5654@example 5655gcc_jit_field *field_x = 5656 gcc_jit_context_new_field (ctxt, NULL, double_type, "x"); 5657gcc_jit_field *field_y = 5658 gcc_jit_context_new_field (ctxt, NULL, double_type, "y"); 5659gcc_jit_field *fields[2] = @{field_x, field_y@}; 5660gcc_jit_struct *coord = 5661 gcc_jit_context_new_struct_type (ctxt, NULL, "coord", 2, fields); 5662@end example 5663 5664@item 5665by creating the structure, then populating it with fields, typically 5666to allow modelling self-referential structs such as: 5667 5668@example 5669struct node @{ int m_hash; struct node *m_next; @}; 5670@end example 5671 5672like this: 5673 5674@example 5675gcc_jit_type *node = 5676 gcc_jit_context_new_opaque_struct (ctxt, NULL, "node"); 5677gcc_jit_type *node_ptr = 5678 gcc_jit_type_get_pointer (node); 5679gcc_jit_field *field_hash = 5680 gcc_jit_context_new_field (ctxt, NULL, int_type, "m_hash"); 5681gcc_jit_field *field_next = 5682 gcc_jit_context_new_field (ctxt, NULL, node_ptr, "m_next"); 5683gcc_jit_field *fields[2] = @{field_hash, field_next@}; 5684gcc_jit_struct_set_fields (node, NULL, 2, fields); 5685@end example 5686@end itemize 5687 5688@geindex gcc_jit_context_new_field (C function) 5689@anchor{topics/types c gcc_jit_context_new_field}@anchor{8b} 5690@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) 5691 5692Construct a new field, with the given type and name. 5693 5694The parameter @code{type} must be non-@cite{void}. 5695 5696The parameter @code{name} must be non-NULL. The call takes a copy of the 5697underlying string, so it is valid to pass in a pointer to an on-stack 5698buffer. 5699@end deffn 5700 5701@geindex gcc_jit_context_new_bitfield (C function) 5702@anchor{topics/types c gcc_jit_context_new_bitfield}@anchor{8c} 5703@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) 5704 5705Construct a new bit field, with the given type width and name. 5706 5707The parameter @code{name} must be non-NULL. The call takes a copy of the 5708underlying string, so it is valid to pass in a pointer to an on-stack 5709buffer. 5710 5711The parameter @code{type} must be an integer type. 5712 5713The parameter @code{width} must be a positive integer that does not exceed the 5714size of @code{type}. 5715 5716This API entrypoint was added in @ref{8d,,LIBGCCJIT_ABI_12}; you can test 5717for its presence using 5718 5719@example 5720#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield 5721@end example 5722@end deffn 5723 5724@geindex gcc_jit_field_as_object (C function) 5725@anchor{topics/types c gcc_jit_field_as_object}@anchor{8e} 5726@deffn {C Function} gcc_jit_object * gcc_jit_field_as_object (gcc_jit_field@w{ }*field) 5727 5728Upcast from field to object. 5729@end deffn 5730 5731@geindex gcc_jit_context_new_struct_type (C function) 5732@anchor{topics/types c gcc_jit_context_new_struct_type}@anchor{8f} 5733@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) 5734 5735@quotation 5736 5737Construct a new struct type, with the given name and fields. 5738 5739The parameter @code{name} must be non-NULL. The call takes a copy of 5740the underlying string, so it is valid to pass in a pointer to an 5741on-stack buffer. 5742@end quotation 5743@end deffn 5744 5745@geindex gcc_jit_context_new_opaque_struct (C function) 5746@anchor{topics/types c gcc_jit_context_new_opaque_struct}@anchor{90} 5747@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) 5748 5749Construct a new struct type, with the given name, but without 5750specifying the fields. The fields can be omitted (in which case the 5751size of the struct is not known), or later specified using 5752@ref{91,,gcc_jit_struct_set_fields()}. 5753 5754The parameter @code{name} must be non-NULL. The call takes a copy of 5755the underlying string, so it is valid to pass in a pointer to an 5756on-stack buffer. 5757@end deffn 5758 5759@geindex gcc_jit_struct_as_type (C function) 5760@anchor{topics/types c gcc_jit_struct_as_type}@anchor{92} 5761@deffn {C Function} gcc_jit_type * gcc_jit_struct_as_type (gcc_jit_struct@w{ }*struct_type) 5762 5763Upcast from struct to type. 5764@end deffn 5765 5766@geindex gcc_jit_struct_set_fields (C function) 5767@anchor{topics/types c gcc_jit_struct_set_fields}@anchor{91} 5768@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) 5769 5770Populate the fields of a formerly-opaque struct type. 5771 5772This can only be called once on a given struct type. 5773@end deffn 5774 5775@geindex gcc_jit_context_new_union_type (C function) 5776@anchor{topics/types c gcc_jit_context_new_union_type}@anchor{93} 5777@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) 5778 5779Construct a new union type, with the given name and fields. 5780 5781The parameter @code{name} must be non-NULL. It is copied, so the input 5782buffer does not need to outlive the call. 5783 5784Example of use: 5785 5786@example 5787 5788union int_or_float 5789@{ 5790 int as_int; 5791 float as_float; 5792@}; 5793 5794void 5795create_code (gcc_jit_context *ctxt, void *user_data) 5796@{ 5797 /* Let's try to inject the equivalent of: 5798 float 5799 test_union (int i) 5800 @{ 5801 union int_or_float u; 5802 u.as_int = i; 5803 return u.as_float; 5804 @} 5805 */ 5806 gcc_jit_type *int_type = 5807 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 5808 gcc_jit_type *float_type = 5809 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); 5810 gcc_jit_field *as_int = 5811 gcc_jit_context_new_field (ctxt, 5812 NULL, 5813 int_type, 5814 "as_int"); 5815 gcc_jit_field *as_float = 5816 gcc_jit_context_new_field (ctxt, 5817 NULL, 5818 float_type, 5819 "as_float"); 5820 gcc_jit_field *fields[] = @{as_int, as_float@}; 5821 gcc_jit_type *union_type = 5822 gcc_jit_context_new_union_type (ctxt, NULL, 5823 "int_or_float", 2, fields); 5824 5825 /* Build the test function. */ 5826 gcc_jit_param *param_i = 5827 gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); 5828 gcc_jit_function *test_fn = 5829 gcc_jit_context_new_function (ctxt, NULL, 5830 GCC_JIT_FUNCTION_EXPORTED, 5831 float_type, 5832 "test_union", 5833 1, ¶m_i, 5834 0); 5835 5836 gcc_jit_lvalue *u = 5837 gcc_jit_function_new_local (test_fn, NULL, 5838 union_type, "u"); 5839 5840 gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); 5841 5842 /* u.as_int = i; */ 5843 gcc_jit_block_add_assignment ( 5844 block, 5845 NULL, 5846 /* "u.as_int = ..." */ 5847 gcc_jit_lvalue_access_field (u, 5848 NULL, 5849 as_int), 5850 gcc_jit_param_as_rvalue (param_i)); 5851 5852 /* return u.as_float; */ 5853 gcc_jit_block_end_with_return ( 5854 block, NULL, 5855 gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (u), 5856 NULL, 5857 as_float)); 5858@} 5859 5860@end example 5861@end deffn 5862 5863@node Function pointer types,,Structures and unions,Types 5864@anchor{topics/types function-pointer-types}@anchor{94} 5865@subsection Function pointer types 5866 5867 5868Function pointer types can be created using 5869@ref{95,,gcc_jit_context_new_function_ptr_type()}. 5870 5871@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 5872@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 5873@c 5874@c This is free software: you can redistribute it and/or modify it 5875@c under the terms of the GNU General Public License as published by 5876@c the Free Software Foundation, either version 3 of the License, or 5877@c (at your option) any later version. 5878@c 5879@c This program is distributed in the hope that it will be useful, but 5880@c WITHOUT ANY WARRANTY; without even the implied warranty of 5881@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5882@c General Public License for more details. 5883@c 5884@c You should have received a copy of the GNU General Public License 5885@c along with this program. If not, see 5886@c <http://www.gnu.org/licenses/>. 5887 5888@node Expressions,Creating and using functions,Types,Topic Reference 5889@anchor{topics/expressions doc}@anchor{96}@anchor{topics/expressions expressions}@anchor{97} 5890@section Expressions 5891 5892 5893@menu 5894* Rvalues:: 5895* Lvalues:: 5896* Working with pointers@comma{} structs and unions: Working with pointers structs and unions. 5897 5898@end menu 5899 5900@node Rvalues,Lvalues,,Expressions 5901@anchor{topics/expressions rvalues}@anchor{98} 5902@subsection Rvalues 5903 5904 5905@geindex gcc_jit_rvalue (C type) 5906@anchor{topics/expressions c gcc_jit_rvalue}@anchor{13} 5907@deffn {C Type} gcc_jit_rvalue 5908@end deffn 5909 5910A @ref{13,,gcc_jit_rvalue *} is an expression that can be computed. 5911 5912It can be simple, e.g.: 5913 5914@quotation 5915 5916 5917@itemize * 5918 5919@item 5920an integer value e.g. @cite{0} or @cite{42} 5921 5922@item 5923a string literal e.g. @cite{“Hello world”} 5924 5925@item 5926a variable e.g. @cite{i}. These are also lvalues (see below). 5927@end itemize 5928@end quotation 5929 5930or compound e.g.: 5931 5932@quotation 5933 5934 5935@itemize * 5936 5937@item 5938a unary expression e.g. @cite{!cond} 5939 5940@item 5941a binary expression e.g. @cite{(a + b)} 5942 5943@item 5944a function call e.g. @cite{get_distance (&player_ship@comma{} &target)} 5945 5946@item 5947etc. 5948@end itemize 5949@end quotation 5950 5951Every rvalue has an associated type, and the API will check to ensure 5952that types match up correctly (otherwise the context will emit an error). 5953 5954@geindex gcc_jit_rvalue_get_type (C function) 5955@anchor{topics/expressions c gcc_jit_rvalue_get_type}@anchor{99} 5956@deffn {C Function} gcc_jit_type *gcc_jit_rvalue_get_type (gcc_jit_rvalue@w{ }*rvalue) 5957 5958Get the type of this rvalue. 5959@end deffn 5960 5961@geindex gcc_jit_rvalue_as_object (C function) 5962@anchor{topics/expressions c gcc_jit_rvalue_as_object}@anchor{14} 5963@deffn {C Function} gcc_jit_object *gcc_jit_rvalue_as_object (gcc_jit_rvalue@w{ }*rvalue) 5964 5965Upcast the given rvalue to be an object. 5966@end deffn 5967 5968@menu 5969* Simple expressions:: 5970* Vector expressions:: 5971* Unary Operations:: 5972* Binary Operations:: 5973* Comparisons:: 5974* Function calls:: 5975* Function pointers:: 5976* Type-coercion:: 5977 5978@end menu 5979 5980@node Simple expressions,Vector expressions,,Rvalues 5981@anchor{topics/expressions simple-expressions}@anchor{9a} 5982@subsubsection Simple expressions 5983 5984 5985@geindex gcc_jit_context_new_rvalue_from_int (C function) 5986@anchor{topics/expressions c gcc_jit_context_new_rvalue_from_int}@anchor{30} 5987@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) 5988 5989Given a numeric type (integer or floating point), build an rvalue for 5990the given constant @code{int} value. 5991@end deffn 5992 5993@geindex gcc_jit_context_new_rvalue_from_long (C function) 5994@anchor{topics/expressions c gcc_jit_context_new_rvalue_from_long}@anchor{9b} 5995@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) 5996 5997Given a numeric type (integer or floating point), build an rvalue for 5998the given constant @code{long} value. 5999@end deffn 6000 6001@geindex gcc_jit_context_zero (C function) 6002@anchor{topics/expressions c gcc_jit_context_zero}@anchor{2b} 6003@deffn {C Function} gcc_jit_rvalue *gcc_jit_context_zero (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type) 6004 6005Given a numeric type (integer or floating point), get the rvalue for 6006zero. Essentially this is just a shortcut for: 6007 6008@example 6009gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0) 6010@end example 6011@end deffn 6012 6013@geindex gcc_jit_context_one (C function) 6014@anchor{topics/expressions c gcc_jit_context_one}@anchor{2f} 6015@deffn {C Function} gcc_jit_rvalue *gcc_jit_context_one (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type) 6016 6017Given a numeric type (integer or floating point), get the rvalue for 6018one. Essentially this is just a shortcut for: 6019 6020@example 6021gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1) 6022@end example 6023@end deffn 6024 6025@geindex gcc_jit_context_new_rvalue_from_double (C function) 6026@anchor{topics/expressions c gcc_jit_context_new_rvalue_from_double}@anchor{31} 6027@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) 6028 6029Given a numeric type (integer or floating point), build an rvalue for 6030the given constant @code{double} value. 6031@end deffn 6032 6033@geindex gcc_jit_context_new_rvalue_from_ptr (C function) 6034@anchor{topics/expressions c gcc_jit_context_new_rvalue_from_ptr}@anchor{9c} 6035@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) 6036 6037Given a pointer type, build an rvalue for the given address. 6038@end deffn 6039 6040@geindex gcc_jit_context_null (C function) 6041@anchor{topics/expressions c gcc_jit_context_null}@anchor{9d} 6042@deffn {C Function} gcc_jit_rvalue *gcc_jit_context_null (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type) 6043 6044Given a pointer type, build an rvalue for @code{NULL}. Essentially this 6045is just a shortcut for: 6046 6047@example 6048gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL) 6049@end example 6050@end deffn 6051 6052@geindex gcc_jit_context_new_string_literal (C function) 6053@anchor{topics/expressions c gcc_jit_context_new_string_literal}@anchor{9e} 6054@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context@w{ }*ctxt, const char@w{ }*value) 6055 6056Generate an rvalue for the given NIL-terminated string, of type 6057@code{GCC_JIT_TYPE_CONST_CHAR_PTR}. 6058 6059The parameter @code{value} must be non-NULL. The call takes a copy of the 6060underlying string, so it is valid to pass in a pointer to an on-stack 6061buffer. 6062@end deffn 6063 6064@node Vector expressions,Unary Operations,Simple expressions,Rvalues 6065@anchor{topics/expressions vector-expressions}@anchor{9f} 6066@subsubsection Vector expressions 6067 6068 6069@geindex gcc_jit_context_new_rvalue_from_vector (C function) 6070@anchor{topics/expressions c gcc_jit_context_new_rvalue_from_vector}@anchor{87} 6071@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) 6072 6073Build a vector rvalue from an array of elements. 6074 6075“vec_type” should be a vector type, created using 6076@ref{85,,gcc_jit_type_get_vector()}. 6077 6078“num_elements” should match that of the vector type. 6079 6080This entrypoint was added in @ref{a0,,LIBGCCJIT_ABI_10}; you can test for 6081its presence using 6082 6083@example 6084#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector 6085@end example 6086@end deffn 6087 6088@node Unary Operations,Binary Operations,Vector expressions,Rvalues 6089@anchor{topics/expressions unary-operations}@anchor{a1} 6090@subsubsection Unary Operations 6091 6092 6093@geindex gcc_jit_context_new_unary_op (C function) 6094@anchor{topics/expressions c gcc_jit_context_new_unary_op}@anchor{a2} 6095@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) 6096 6097Build a unary operation out of an input rvalue. 6098 6099The parameter @code{result_type} must be a numeric type. 6100@end deffn 6101 6102@geindex gcc_jit_unary_op (C type) 6103@anchor{topics/expressions c gcc_jit_unary_op}@anchor{a3} 6104@deffn {C Type} enum gcc_jit_unary_op 6105@end deffn 6106 6107The available unary operations are: 6108 6109 6110@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6111@headitem 6112 6113Unary Operation 6114 6115@tab 6116 6117C equivalent 6118 6119@item 6120 6121@ref{a4,,GCC_JIT_UNARY_OP_MINUS} 6122 6123@tab 6124 6125@cite{-(EXPR)} 6126 6127@item 6128 6129@ref{a5,,GCC_JIT_UNARY_OP_BITWISE_NEGATE} 6130 6131@tab 6132 6133@cite{~(EXPR)} 6134 6135@item 6136 6137@ref{a6,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE} 6138 6139@tab 6140 6141@cite{!(EXPR)} 6142 6143@item 6144 6145@ref{a7,,GCC_JIT_UNARY_OP_ABS} 6146 6147@tab 6148 6149@cite{abs (EXPR)} 6150 6151@end multitable 6152 6153 6154@geindex GCC_JIT_UNARY_OP_MINUS (C macro) 6155@anchor{topics/expressions c GCC_JIT_UNARY_OP_MINUS}@anchor{a4} 6156@deffn {C Macro} GCC_JIT_UNARY_OP_MINUS 6157 6158Negate an arithmetic value; analogous to: 6159 6160@example 6161-(EXPR) 6162@end example 6163 6164in C. 6165@end deffn 6166 6167@geindex GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro) 6168@anchor{topics/expressions c GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{a5} 6169@deffn {C Macro} GCC_JIT_UNARY_OP_BITWISE_NEGATE 6170 6171Bitwise negation of an integer value (one’s complement); analogous 6172to: 6173 6174@example 6175~(EXPR) 6176@end example 6177 6178in C. 6179@end deffn 6180 6181@geindex GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro) 6182@anchor{topics/expressions c GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{a6} 6183@deffn {C Macro} GCC_JIT_UNARY_OP_LOGICAL_NEGATE 6184 6185Logical negation of an arithmetic or pointer value; analogous to: 6186 6187@example 6188!(EXPR) 6189@end example 6190 6191in C. 6192@end deffn 6193 6194@geindex GCC_JIT_UNARY_OP_ABS (C macro) 6195@anchor{topics/expressions c GCC_JIT_UNARY_OP_ABS}@anchor{a7} 6196@deffn {C Macro} GCC_JIT_UNARY_OP_ABS 6197 6198Absolute value of an arithmetic expression; analogous to: 6199 6200@example 6201abs (EXPR) 6202@end example 6203 6204in C. 6205@end deffn 6206 6207@node Binary Operations,Comparisons,Unary Operations,Rvalues 6208@anchor{topics/expressions binary-operations}@anchor{a8} 6209@subsubsection Binary Operations 6210 6211 6212@geindex gcc_jit_context_new_binary_op (C function) 6213@anchor{topics/expressions c gcc_jit_context_new_binary_op}@anchor{12} 6214@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) 6215 6216Build a binary operation out of two constituent rvalues. 6217 6218The parameter @code{result_type} must be a numeric type. 6219@end deffn 6220 6221@geindex gcc_jit_binary_op (C type) 6222@anchor{topics/expressions c gcc_jit_binary_op}@anchor{a9} 6223@deffn {C Type} enum gcc_jit_binary_op 6224@end deffn 6225 6226The available binary operations are: 6227 6228 6229@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6230@headitem 6231 6232Binary Operation 6233 6234@tab 6235 6236C equivalent 6237 6238@item 6239 6240@ref{aa,,GCC_JIT_BINARY_OP_PLUS} 6241 6242@tab 6243 6244@cite{x + y} 6245 6246@item 6247 6248@ref{ab,,GCC_JIT_BINARY_OP_MINUS} 6249 6250@tab 6251 6252@cite{x - y} 6253 6254@item 6255 6256@ref{ac,,GCC_JIT_BINARY_OP_MULT} 6257 6258@tab 6259 6260@cite{x * y} 6261 6262@item 6263 6264@ref{ad,,GCC_JIT_BINARY_OP_DIVIDE} 6265 6266@tab 6267 6268@cite{x / y} 6269 6270@item 6271 6272@ref{ae,,GCC_JIT_BINARY_OP_MODULO} 6273 6274@tab 6275 6276@cite{x % y} 6277 6278@item 6279 6280@ref{af,,GCC_JIT_BINARY_OP_BITWISE_AND} 6281 6282@tab 6283 6284@cite{x & y} 6285 6286@item 6287 6288@ref{b0,,GCC_JIT_BINARY_OP_BITWISE_XOR} 6289 6290@tab 6291 6292@cite{x ^ y} 6293 6294@item 6295 6296@ref{b1,,GCC_JIT_BINARY_OP_BITWISE_OR} 6297 6298@tab 6299 6300@cite{x | y} 6301 6302@item 6303 6304@ref{b2,,GCC_JIT_BINARY_OP_LOGICAL_AND} 6305 6306@tab 6307 6308@cite{x && y} 6309 6310@item 6311 6312@ref{b3,,GCC_JIT_BINARY_OP_LOGICAL_OR} 6313 6314@tab 6315 6316@cite{x || y} 6317 6318@item 6319 6320@ref{b4,,GCC_JIT_BINARY_OP_LSHIFT} 6321 6322@tab 6323 6324@cite{x << y} 6325 6326@item 6327 6328@ref{b5,,GCC_JIT_BINARY_OP_RSHIFT} 6329 6330@tab 6331 6332@cite{x >> y} 6333 6334@end multitable 6335 6336 6337@geindex GCC_JIT_BINARY_OP_PLUS (C macro) 6338@anchor{topics/expressions c GCC_JIT_BINARY_OP_PLUS}@anchor{aa} 6339@deffn {C Macro} GCC_JIT_BINARY_OP_PLUS 6340 6341Addition of arithmetic values; analogous to: 6342 6343@example 6344(EXPR_A) + (EXPR_B) 6345@end example 6346 6347in C. 6348 6349For pointer addition, use @ref{b6,,gcc_jit_context_new_array_access()}. 6350@end deffn 6351 6352@geindex GCC_JIT_BINARY_OP_MINUS (C macro) 6353@anchor{topics/expressions c GCC_JIT_BINARY_OP_MINUS}@anchor{ab} 6354@deffn {C Macro} GCC_JIT_BINARY_OP_MINUS 6355 6356Subtraction of arithmetic values; analogous to: 6357 6358@example 6359(EXPR_A) - (EXPR_B) 6360@end example 6361 6362in C. 6363@end deffn 6364 6365@geindex GCC_JIT_BINARY_OP_MULT (C macro) 6366@anchor{topics/expressions c GCC_JIT_BINARY_OP_MULT}@anchor{ac} 6367@deffn {C Macro} GCC_JIT_BINARY_OP_MULT 6368 6369Multiplication of a pair of arithmetic values; analogous to: 6370 6371@example 6372(EXPR_A) * (EXPR_B) 6373@end example 6374 6375in C. 6376@end deffn 6377 6378@geindex GCC_JIT_BINARY_OP_DIVIDE (C macro) 6379@anchor{topics/expressions c GCC_JIT_BINARY_OP_DIVIDE}@anchor{ad} 6380@deffn {C Macro} GCC_JIT_BINARY_OP_DIVIDE 6381 6382Quotient of division of arithmetic values; analogous to: 6383 6384@example 6385(EXPR_A) / (EXPR_B) 6386@end example 6387 6388in C. 6389 6390The result type affects the kind of division: if the result type is 6391integer-based, then the result is truncated towards zero, whereas 6392a floating-point result type indicates floating-point division. 6393@end deffn 6394 6395@geindex GCC_JIT_BINARY_OP_MODULO (C macro) 6396@anchor{topics/expressions c GCC_JIT_BINARY_OP_MODULO}@anchor{ae} 6397@deffn {C Macro} GCC_JIT_BINARY_OP_MODULO 6398 6399Remainder of division of arithmetic values; analogous to: 6400 6401@example 6402(EXPR_A) % (EXPR_B) 6403@end example 6404 6405in C. 6406@end deffn 6407 6408@geindex GCC_JIT_BINARY_OP_BITWISE_AND (C macro) 6409@anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{af} 6410@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_AND 6411 6412Bitwise AND; analogous to: 6413 6414@example 6415(EXPR_A) & (EXPR_B) 6416@end example 6417 6418in C. 6419@end deffn 6420 6421@geindex GCC_JIT_BINARY_OP_BITWISE_XOR (C macro) 6422@anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{b0} 6423@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_XOR 6424 6425Bitwise exclusive OR; analogous to: 6426 6427@example 6428(EXPR_A) ^ (EXPR_B) 6429@end example 6430 6431in C. 6432@end deffn 6433 6434@geindex GCC_JIT_BINARY_OP_BITWISE_OR (C macro) 6435@anchor{topics/expressions c GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{b1} 6436@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_OR 6437 6438Bitwise inclusive OR; analogous to: 6439 6440@example 6441(EXPR_A) | (EXPR_B) 6442@end example 6443 6444in C. 6445@end deffn 6446 6447@geindex GCC_JIT_BINARY_OP_LOGICAL_AND (C macro) 6448@anchor{topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{b2} 6449@deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_AND 6450 6451Logical AND; analogous to: 6452 6453@example 6454(EXPR_A) && (EXPR_B) 6455@end example 6456 6457in C. 6458@end deffn 6459 6460@geindex GCC_JIT_BINARY_OP_LOGICAL_OR (C macro) 6461@anchor{topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{b3} 6462@deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_OR 6463 6464Logical OR; analogous to: 6465 6466@example 6467(EXPR_A) || (EXPR_B) 6468@end example 6469 6470in C. 6471@end deffn 6472 6473@geindex GCC_JIT_BINARY_OP_LSHIFT (C macro) 6474@anchor{topics/expressions c GCC_JIT_BINARY_OP_LSHIFT}@anchor{b4} 6475@deffn {C Macro} GCC_JIT_BINARY_OP_LSHIFT 6476 6477Left shift; analogous to: 6478 6479@example 6480(EXPR_A) << (EXPR_B) 6481@end example 6482 6483in C. 6484@end deffn 6485 6486@geindex GCC_JIT_BINARY_OP_RSHIFT (C macro) 6487@anchor{topics/expressions c GCC_JIT_BINARY_OP_RSHIFT}@anchor{b5} 6488@deffn {C Macro} GCC_JIT_BINARY_OP_RSHIFT 6489 6490Right shift; analogous to: 6491 6492@example 6493(EXPR_A) >> (EXPR_B) 6494@end example 6495 6496in C. 6497@end deffn 6498 6499@node Comparisons,Function calls,Binary Operations,Rvalues 6500@anchor{topics/expressions comparisons}@anchor{b7} 6501@subsubsection Comparisons 6502 6503 6504@geindex gcc_jit_context_new_comparison (C function) 6505@anchor{topics/expressions c gcc_jit_context_new_comparison}@anchor{2c} 6506@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) 6507 6508Build a boolean rvalue out of the comparison of two other rvalues. 6509@end deffn 6510 6511@geindex gcc_jit_comparison (C type) 6512@anchor{topics/expressions c gcc_jit_comparison}@anchor{b8} 6513@deffn {C Type} enum gcc_jit_comparison 6514@end deffn 6515 6516 6517@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxx} 6518@headitem 6519 6520Comparison 6521 6522@tab 6523 6524C equivalent 6525 6526@item 6527 6528@code{GCC_JIT_COMPARISON_EQ} 6529 6530@tab 6531 6532@cite{x == y} 6533 6534@item 6535 6536@code{GCC_JIT_COMPARISON_NE} 6537 6538@tab 6539 6540@cite{x != y} 6541 6542@item 6543 6544@code{GCC_JIT_COMPARISON_LT} 6545 6546@tab 6547 6548@cite{x < y} 6549 6550@item 6551 6552@code{GCC_JIT_COMPARISON_LE} 6553 6554@tab 6555 6556@cite{x <= y} 6557 6558@item 6559 6560@code{GCC_JIT_COMPARISON_GT} 6561 6562@tab 6563 6564@cite{x > y} 6565 6566@item 6567 6568@code{GCC_JIT_COMPARISON_GE} 6569 6570@tab 6571 6572@cite{x >= y} 6573 6574@end multitable 6575 6576 6577@node Function calls,Function pointers,Comparisons,Rvalues 6578@anchor{topics/expressions function-calls}@anchor{b9} 6579@subsubsection Function calls 6580 6581 6582@geindex gcc_jit_context_new_call (C function) 6583@anchor{topics/expressions c gcc_jit_context_new_call}@anchor{ba} 6584@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) 6585 6586Given a function and the given table of argument rvalues, construct a 6587call to the function, with the result as an rvalue. 6588 6589@cartouche 6590@quotation Note 6591@ref{ba,,gcc_jit_context_new_call()} merely builds a 6592@ref{13,,gcc_jit_rvalue} i.e. an expression that can be evaluated, 6593perhaps as part of a more complicated expression. 6594The call @emph{won’t} happen unless you add a statement to a function 6595that evaluates the expression. 6596 6597For example, if you want to call a function and discard the result 6598(or to call a function with @code{void} return type), use 6599@ref{bb,,gcc_jit_block_add_eval()}: 6600 6601@example 6602/* Add "(void)printf (arg0, arg1);". */ 6603gcc_jit_block_add_eval ( 6604 block, NULL, 6605 gcc_jit_context_new_call ( 6606 ctxt, 6607 NULL, 6608 printf_func, 6609 2, args)); 6610@end example 6611@end quotation 6612@end cartouche 6613@end deffn 6614 6615@geindex gcc_jit_context_new_call_through_ptr (C function) 6616@anchor{topics/expressions c gcc_jit_context_new_call_through_ptr}@anchor{bc} 6617@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) 6618 6619Given an rvalue of function pointer type (e.g. from 6620@ref{95,,gcc_jit_context_new_function_ptr_type()}), and the given table of 6621argument rvalues, construct a call to the function pointer, with the 6622result as an rvalue. 6623 6624@cartouche 6625@quotation Note 6626The same caveat as for @ref{ba,,gcc_jit_context_new_call()} applies. 6627@end quotation 6628@end cartouche 6629@end deffn 6630 6631@geindex gcc_jit_rvalue_set_bool_require_tail_call (C function) 6632@anchor{topics/expressions c gcc_jit_rvalue_set_bool_require_tail_call}@anchor{bd} 6633@deffn {C Function} void gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue@w{ }*call, int@w{ }require_tail_call) 6634 6635Given an @ref{13,,gcc_jit_rvalue *} for a call created through 6636@ref{ba,,gcc_jit_context_new_call()} or 6637@ref{bc,,gcc_jit_context_new_call_through_ptr()}, mark/clear the 6638call as needing tail-call optimization. The optimizer will 6639attempt to optimize the call into a jump instruction; if it is 6640unable to do do, an error will be emitted. 6641 6642This may be useful when implementing functions that use the 6643continuation-passing style (e.g. for functional programming 6644languages), in which every function “returns” by calling a 6645“continuation” function pointer. This call must be 6646guaranteed to be implemented as a jump, otherwise the program 6647could consume an arbitrary amount of stack space as it executed. 6648 6649This entrypoint was added in @ref{be,,LIBGCCJIT_ABI_6}; you can test for 6650its presence using 6651 6652@example 6653#ifdef LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call 6654@end example 6655@end deffn 6656 6657@node Function pointers,Type-coercion,Function calls,Rvalues 6658@anchor{topics/expressions function-pointers}@anchor{bf} 6659@subsubsection Function pointers 6660 6661 6662Function pointers can be obtained: 6663 6664@quotation 6665 6666 6667@itemize * 6668 6669@item 6670from a @ref{29,,gcc_jit_function} using 6671@ref{c0,,gcc_jit_function_get_address()}, or 6672 6673@item 6674from an existing function using 6675@ref{9c,,gcc_jit_context_new_rvalue_from_ptr()}, 6676using a function pointer type obtained using 6677@ref{95,,gcc_jit_context_new_function_ptr_type()}. 6678@end itemize 6679@end quotation 6680 6681@node Type-coercion,,Function pointers,Rvalues 6682@anchor{topics/expressions type-coercion}@anchor{c1} 6683@subsubsection Type-coercion 6684 6685 6686@geindex gcc_jit_context_new_cast (C function) 6687@anchor{topics/expressions c gcc_jit_context_new_cast}@anchor{c2} 6688@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) 6689 6690Given an rvalue of T, construct another rvalue of another type. 6691 6692Currently only a limited set of conversions are possible: 6693 6694@quotation 6695 6696 6697@itemize * 6698 6699@item 6700int <-> float 6701 6702@item 6703int <-> bool 6704 6705@item 6706P* <-> Q*, for pointer types P and Q 6707@end itemize 6708@end quotation 6709@end deffn 6710 6711@node Lvalues,Working with pointers structs and unions,Rvalues,Expressions 6712@anchor{topics/expressions lvalues}@anchor{c3} 6713@subsection Lvalues 6714 6715 6716@geindex gcc_jit_lvalue (C type) 6717@anchor{topics/expressions c gcc_jit_lvalue}@anchor{24} 6718@deffn {C Type} gcc_jit_lvalue 6719@end deffn 6720 6721An lvalue is something that can of the @emph{left}-hand side of an assignment: 6722a storage area (such as a variable). It is also usable as an rvalue, 6723where the rvalue is computed by reading from the storage area. 6724 6725@geindex gcc_jit_lvalue_as_object (C function) 6726@anchor{topics/expressions c gcc_jit_lvalue_as_object}@anchor{c4} 6727@deffn {C Function} gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue@w{ }*lvalue) 6728 6729Upcast an lvalue to be an object. 6730@end deffn 6731 6732@geindex gcc_jit_lvalue_as_rvalue (C function) 6733@anchor{topics/expressions c gcc_jit_lvalue_as_rvalue}@anchor{c5} 6734@deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue@w{ }*lvalue) 6735 6736Upcast an lvalue to be an rvalue. 6737@end deffn 6738 6739@geindex gcc_jit_lvalue_get_address (C function) 6740@anchor{topics/expressions c gcc_jit_lvalue_get_address}@anchor{c6} 6741@deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_get_address (gcc_jit_lvalue@w{ }*lvalue, gcc_jit_location@w{ }*loc) 6742 6743Take the address of an lvalue; analogous to: 6744 6745@example 6746&(EXPR) 6747@end example 6748 6749in C. 6750@end deffn 6751 6752@menu 6753* Global variables:: 6754 6755@end menu 6756 6757@node Global variables,,,Lvalues 6758@anchor{topics/expressions global-variables}@anchor{c7} 6759@subsubsection Global variables 6760 6761 6762@geindex gcc_jit_context_new_global (C function) 6763@anchor{topics/expressions c gcc_jit_context_new_global}@anchor{c8} 6764@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) 6765 6766Add a new global variable of the given type and name to the context. 6767 6768The parameter @code{type} must be non-@cite{void}. 6769 6770The parameter @code{name} must be non-NULL. The call takes a copy of the 6771underlying string, so it is valid to pass in a pointer to an on-stack 6772buffer. 6773 6774The “kind” parameter determines the visibility of the “global” outside 6775of the @ref{16,,gcc_jit_result}: 6776 6777@geindex gcc_jit_global_kind (C type) 6778@anchor{topics/expressions c gcc_jit_global_kind}@anchor{c9} 6779@deffn {C Type} enum gcc_jit_global_kind 6780@end deffn 6781 6782@geindex GCC_JIT_GLOBAL_EXPORTED (C macro) 6783@anchor{topics/expressions c GCC_JIT_GLOBAL_EXPORTED}@anchor{ca} 6784@deffn {C Macro} GCC_JIT_GLOBAL_EXPORTED 6785 6786Global is defined by the client code and is visible 6787by name outside of this JIT context via 6788@ref{cb,,gcc_jit_result_get_global()} (and this value is required for 6789the global to be accessible via that entrypoint). 6790@end deffn 6791 6792@geindex GCC_JIT_GLOBAL_INTERNAL (C macro) 6793@anchor{topics/expressions c GCC_JIT_GLOBAL_INTERNAL}@anchor{cc} 6794@deffn {C Macro} GCC_JIT_GLOBAL_INTERNAL 6795 6796Global is defined by the client code, but is invisible 6797outside of it. Analogous to a “static” global within a .c file. 6798Specifically, the variable will only be visible within this 6799context and within child contexts. 6800@end deffn 6801 6802@geindex GCC_JIT_GLOBAL_IMPORTED (C macro) 6803@anchor{topics/expressions c GCC_JIT_GLOBAL_IMPORTED}@anchor{cd} 6804@deffn {C Macro} GCC_JIT_GLOBAL_IMPORTED 6805 6806Global is not defined by the client code; we’re merely 6807referring to it. Analogous to using an “extern” global from a 6808header file. 6809@end deffn 6810@end deffn 6811 6812@geindex gcc_jit_global_set_initializer (C function) 6813@anchor{topics/expressions c gcc_jit_global_set_initializer}@anchor{ce} 6814@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) 6815 6816Set an initializer for @code{global} using the memory content pointed 6817by @code{blob} for @code{num_bytes}. @code{global} must be an array of an 6818integral type. Return the global itself. 6819 6820The parameter @code{blob} must be non-NULL. The call copies the memory 6821pointed by @code{blob} for @code{num_bytes} bytes, so it is valid to pass 6822in a pointer to an on-stack buffer. The content will be stored in 6823the compilation unit and used as initialization value of the array. 6824 6825This entrypoint was added in @ref{cf,,LIBGCCJIT_ABI_14}; you can test for 6826its presence using 6827 6828@example 6829#ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer 6830@end example 6831@end deffn 6832 6833@node Working with pointers structs and unions,,Lvalues,Expressions 6834@anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{d0} 6835@subsection Working with pointers, structs and unions 6836 6837 6838@geindex gcc_jit_rvalue_dereference (C function) 6839@anchor{topics/expressions c gcc_jit_rvalue_dereference}@anchor{d1} 6840@deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference (gcc_jit_rvalue@w{ }*rvalue, gcc_jit_location@w{ }*loc) 6841 6842Given an rvalue of pointer type @code{T *}, dereferencing the pointer, 6843getting an lvalue of type @code{T}. Analogous to: 6844 6845@example 6846*(EXPR) 6847@end example 6848 6849in C. 6850@end deffn 6851 6852Field access is provided separately for both lvalues and rvalues. 6853 6854@geindex gcc_jit_lvalue_access_field (C function) 6855@anchor{topics/expressions c gcc_jit_lvalue_access_field}@anchor{d2} 6856@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) 6857 6858Given an lvalue of struct or union type, access the given field, 6859getting an lvalue of the field’s type. Analogous to: 6860 6861@example 6862(EXPR).field = ...; 6863@end example 6864 6865in C. 6866@end deffn 6867 6868@geindex gcc_jit_rvalue_access_field (C function) 6869@anchor{topics/expressions c gcc_jit_rvalue_access_field}@anchor{d3} 6870@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) 6871 6872Given an rvalue of struct or union type, access the given field 6873as an rvalue. Analogous to: 6874 6875@example 6876(EXPR).field 6877@end example 6878 6879in C. 6880@end deffn 6881 6882@geindex gcc_jit_rvalue_dereference_field (C function) 6883@anchor{topics/expressions c gcc_jit_rvalue_dereference_field}@anchor{d4} 6884@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) 6885 6886Given an rvalue of pointer type @code{T *} where T is of struct or union 6887type, access the given field as an lvalue. Analogous to: 6888 6889@example 6890(EXPR)->field 6891@end example 6892 6893in C, itself equivalent to @code{(*EXPR).FIELD}. 6894@end deffn 6895 6896@geindex gcc_jit_context_new_array_access (C function) 6897@anchor{topics/expressions c gcc_jit_context_new_array_access}@anchor{b6} 6898@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) 6899 6900Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at 6901the given index, using standard C array indexing rules i.e. each 6902increment of @code{index} corresponds to @code{sizeof(T)} bytes. 6903Analogous to: 6904 6905@example 6906PTR[INDEX] 6907@end example 6908 6909in C (or, indeed, to @code{PTR + INDEX}). 6910@end deffn 6911 6912@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 6913@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 6914@c 6915@c This is free software: you can redistribute it and/or modify it 6916@c under the terms of the GNU General Public License as published by 6917@c the Free Software Foundation, either version 3 of the License, or 6918@c (at your option) any later version. 6919@c 6920@c This program is distributed in the hope that it will be useful, but 6921@c WITHOUT ANY WARRANTY; without even the implied warranty of 6922@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 6923@c General Public License for more details. 6924@c 6925@c You should have received a copy of the GNU General Public License 6926@c along with this program. If not, see 6927@c <http://www.gnu.org/licenses/>. 6928 6929@node Creating and using functions,Function pointers<2>,Expressions,Topic Reference 6930@anchor{topics/functions doc}@anchor{d5}@anchor{topics/functions creating-and-using-functions}@anchor{d6} 6931@section Creating and using functions 6932 6933 6934@menu 6935* Params:: 6936* Functions:: 6937* Blocks:: 6938* Statements:: 6939 6940@end menu 6941 6942@node Params,Functions,,Creating and using functions 6943@anchor{topics/functions params}@anchor{d7} 6944@subsection Params 6945 6946 6947@geindex gcc_jit_param (C type) 6948@anchor{topics/functions c gcc_jit_param}@anchor{25} 6949@deffn {C Type} gcc_jit_param 6950 6951A @cite{gcc_jit_param} represents a parameter to a function. 6952@end deffn 6953 6954@geindex gcc_jit_context_new_param (C function) 6955@anchor{topics/functions c gcc_jit_context_new_param}@anchor{10} 6956@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) 6957 6958In preparation for creating a function, create a new parameter of the 6959given type and name. 6960 6961The parameter @code{type} must be non-@cite{void}. 6962 6963The parameter @code{name} must be non-NULL. The call takes a copy of the 6964underlying string, so it is valid to pass in a pointer to an on-stack 6965buffer. 6966@end deffn 6967 6968Parameters are lvalues, and thus are also rvalues (and objects), so the 6969following upcasts are available: 6970 6971@geindex gcc_jit_param_as_lvalue (C function) 6972@anchor{topics/functions c gcc_jit_param_as_lvalue}@anchor{d8} 6973@deffn {C Function} gcc_jit_lvalue * gcc_jit_param_as_lvalue (gcc_jit_param@w{ }*param) 6974 6975Upcasting from param to lvalue. 6976@end deffn 6977 6978@geindex gcc_jit_param_as_rvalue (C function) 6979@anchor{topics/functions c gcc_jit_param_as_rvalue}@anchor{d9} 6980@deffn {C Function} gcc_jit_rvalue * gcc_jit_param_as_rvalue (gcc_jit_param@w{ }*param) 6981 6982Upcasting from param to rvalue. 6983@end deffn 6984 6985@geindex gcc_jit_param_as_object (C function) 6986@anchor{topics/functions c gcc_jit_param_as_object}@anchor{da} 6987@deffn {C Function} gcc_jit_object * gcc_jit_param_as_object (gcc_jit_param@w{ }*param) 6988 6989Upcasting from param to object. 6990@end deffn 6991 6992@node Functions,Blocks,Params,Creating and using functions 6993@anchor{topics/functions functions}@anchor{db} 6994@subsection Functions 6995 6996 6997@geindex gcc_jit_function (C type) 6998@anchor{topics/functions c gcc_jit_function}@anchor{29} 6999@deffn {C Type} gcc_jit_function 7000 7001A @cite{gcc_jit_function} represents a function - either one that we’re 7002creating ourselves, or one that we’re referencing. 7003@end deffn 7004 7005@geindex gcc_jit_context_new_function (C function) 7006@anchor{topics/functions c gcc_jit_context_new_function}@anchor{11} 7007@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) 7008 7009Create a gcc_jit_function with the given name and parameters. 7010 7011@geindex gcc_jit_function_kind (C type) 7012@anchor{topics/functions c gcc_jit_function_kind}@anchor{dc} 7013@deffn {C Type} enum gcc_jit_function_kind 7014@end deffn 7015 7016This enum controls the kind of function created, and has the following 7017values: 7018 7019@quotation 7020 7021@geindex GCC_JIT_FUNCTION_EXPORTED (C macro) 7022@anchor{topics/functions c GCC_JIT_FUNCTION_EXPORTED}@anchor{dd} 7023@deffn {C Macro} GCC_JIT_FUNCTION_EXPORTED 7024 7025Function is defined by the client code and visible 7026by name outside of the JIT. 7027 7028This value is required if you want to extract machine code 7029for this function from a @ref{16,,gcc_jit_result} via 7030@ref{17,,gcc_jit_result_get_code()}. 7031@end deffn 7032 7033@geindex GCC_JIT_FUNCTION_INTERNAL (C macro) 7034@anchor{topics/functions c GCC_JIT_FUNCTION_INTERNAL}@anchor{de} 7035@deffn {C Macro} GCC_JIT_FUNCTION_INTERNAL 7036 7037Function is defined by the client code, but is invisible 7038outside of the JIT. Analogous to a “static” function. 7039@end deffn 7040 7041@geindex GCC_JIT_FUNCTION_IMPORTED (C macro) 7042@anchor{topics/functions c GCC_JIT_FUNCTION_IMPORTED}@anchor{df} 7043@deffn {C Macro} GCC_JIT_FUNCTION_IMPORTED 7044 7045Function is not defined by the client code; we’re merely 7046referring to it. Analogous to using an “extern” function from a 7047header file. 7048@end deffn 7049 7050@geindex GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro) 7051@anchor{topics/functions c GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{e0} 7052@deffn {C Macro} GCC_JIT_FUNCTION_ALWAYS_INLINE 7053 7054Function is only ever inlined into other functions, and is 7055invisible outside of the JIT. 7056 7057Analogous to prefixing with @code{inline} and adding 7058@code{__attribute__((always_inline))} 7059 7060Inlining will only occur when the optimization level is 7061above 0; when optimization is off, this is essentially the 7062same as GCC_JIT_FUNCTION_INTERNAL. 7063@end deffn 7064@end quotation 7065 7066The parameter @code{name} must be non-NULL. The call takes a copy of the 7067underlying string, so it is valid to pass in a pointer to an on-stack 7068buffer. 7069@end deffn 7070 7071@geindex gcc_jit_context_get_builtin_function (C function) 7072@anchor{topics/functions c gcc_jit_context_get_builtin_function}@anchor{e1} 7073@deffn {C Function} gcc_jit_function * gcc_jit_context_get_builtin_function (gcc_jit_context@w{ }*ctxt, const char@w{ }*name) 7074 7075Get the @ref{29,,gcc_jit_function} for the built-in function with the 7076given name. For example: 7077 7078@example 7079gcc_jit_function *fn 7080 = gcc_jit_context_get_builtin_function (ctxt, "__builtin_memcpy"); 7081@end example 7082 7083@cartouche 7084@quotation Note 7085Due to technical limitations with how libgccjit interacts with 7086the insides of GCC, not all built-in functions are supported. More 7087precisely, not all types are supported for parameters of built-in 7088functions from libgccjit. Attempts to get a built-in function that 7089uses such a parameter will lead to an error being emitted within 7090the context. 7091@end quotation 7092@end cartouche 7093@end deffn 7094 7095@geindex gcc_jit_function_as_object (C function) 7096@anchor{topics/functions c gcc_jit_function_as_object}@anchor{e2} 7097@deffn {C Function} gcc_jit_object * gcc_jit_function_as_object (gcc_jit_function@w{ }*func) 7098 7099Upcasting from function to object. 7100@end deffn 7101 7102@geindex gcc_jit_function_get_param (C function) 7103@anchor{topics/functions c gcc_jit_function_get_param}@anchor{e3} 7104@deffn {C Function} gcc_jit_param * gcc_jit_function_get_param (gcc_jit_function@w{ }*func, int@w{ }index) 7105 7106Get the param of the given index (0-based). 7107@end deffn 7108 7109@geindex gcc_jit_function_dump_to_dot (C function) 7110@anchor{topics/functions c gcc_jit_function_dump_to_dot}@anchor{33} 7111@deffn {C Function} void gcc_jit_function_dump_to_dot (gcc_jit_function@w{ }*func, const char@w{ }*path) 7112 7113Emit the function in graphviz format to the given path. 7114@end deffn 7115 7116@geindex gcc_jit_function_new_local (C function) 7117@anchor{topics/functions c gcc_jit_function_new_local}@anchor{26} 7118@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) 7119 7120Create a new local variable within the function, of the given type and 7121name. 7122 7123The parameter @code{type} must be non-@cite{void}. 7124 7125The parameter @code{name} must be non-NULL. The call takes a copy of the 7126underlying string, so it is valid to pass in a pointer to an on-stack 7127buffer. 7128@end deffn 7129 7130@node Blocks,Statements,Functions,Creating and using functions 7131@anchor{topics/functions blocks}@anchor{e4} 7132@subsection Blocks 7133 7134 7135@geindex gcc_jit_block (C type) 7136@anchor{topics/functions c gcc_jit_block}@anchor{28} 7137@deffn {C Type} gcc_jit_block 7138 7139A @cite{gcc_jit_block} represents a basic block within a function i.e. a 7140sequence of statements with a single entry point and a single exit 7141point. 7142 7143The first basic block that you create within a function will 7144be the entrypoint. 7145 7146Each basic block that you create within a function must be 7147terminated, either with a conditional, a jump, a return, or a 7148switch. 7149 7150It’s legal to have multiple basic blocks that return within 7151one function. 7152@end deffn 7153 7154@geindex gcc_jit_function_new_block (C function) 7155@anchor{topics/functions c gcc_jit_function_new_block}@anchor{e5} 7156@deffn {C Function} gcc_jit_block * gcc_jit_function_new_block (gcc_jit_function@w{ }*func, const char@w{ }*name) 7157 7158Create a basic block of the given name. The name may be NULL, but 7159providing meaningful names is often helpful when debugging: it may 7160show up in dumps of the internal representation, and in error 7161messages. It is copied, so the input buffer does not need to outlive 7162the call; you can pass in a pointer to an on-stack buffer, e.g.: 7163 7164@example 7165for (pc = 0; pc < fn->fn_num_ops; pc++) 7166 @{ 7167 char buf[16]; 7168 sprintf (buf, "instr%i", pc); 7169 state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); 7170 @} 7171@end example 7172@end deffn 7173 7174@geindex gcc_jit_block_as_object (C function) 7175@anchor{topics/functions c gcc_jit_block_as_object}@anchor{e6} 7176@deffn {C Function} gcc_jit_object * gcc_jit_block_as_object (gcc_jit_block@w{ }*block) 7177 7178Upcast from block to object. 7179@end deffn 7180 7181@geindex gcc_jit_block_get_function (C function) 7182@anchor{topics/functions c gcc_jit_block_get_function}@anchor{e7} 7183@deffn {C Function} gcc_jit_function * gcc_jit_block_get_function (gcc_jit_block@w{ }*block) 7184 7185Which function is this block within? 7186@end deffn 7187 7188@node Statements,,Blocks,Creating and using functions 7189@anchor{topics/functions statements}@anchor{e8} 7190@subsection Statements 7191 7192 7193@geindex gcc_jit_block_add_eval (C function) 7194@anchor{topics/functions c gcc_jit_block_add_eval}@anchor{bb} 7195@deffn {C Function} void gcc_jit_block_add_eval (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue) 7196 7197Add evaluation of an rvalue, discarding the result 7198(e.g. a function call that “returns” void). 7199 7200This is equivalent to this C code: 7201 7202@example 7203(void)expression; 7204@end example 7205@end deffn 7206 7207@geindex gcc_jit_block_add_assignment (C function) 7208@anchor{topics/functions c gcc_jit_block_add_assignment}@anchor{2a} 7209@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) 7210 7211Add evaluation of an rvalue, assigning the result to the given 7212lvalue. 7213 7214This is roughly equivalent to this C code: 7215 7216@example 7217lvalue = rvalue; 7218@end example 7219@end deffn 7220 7221@geindex gcc_jit_block_add_assignment_op (C function) 7222@anchor{topics/functions c gcc_jit_block_add_assignment_op}@anchor{2e} 7223@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) 7224 7225Add evaluation of an rvalue, using the result to modify an 7226lvalue. 7227 7228This is analogous to “+=” and friends: 7229 7230@example 7231lvalue += rvalue; 7232lvalue *= rvalue; 7233lvalue /= rvalue; 7234@end example 7235 7236etc. For example: 7237 7238@example 7239/* "i++" */ 7240gcc_jit_block_add_assignment_op ( 7241 loop_body, NULL, 7242 i, 7243 GCC_JIT_BINARY_OP_PLUS, 7244 gcc_jit_context_one (ctxt, int_type)); 7245@end example 7246@end deffn 7247 7248@geindex gcc_jit_block_add_comment (C function) 7249@anchor{topics/functions c gcc_jit_block_add_comment}@anchor{3d} 7250@deffn {C Function} void gcc_jit_block_add_comment (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*text) 7251 7252Add a no-op textual comment to the internal representation of the 7253code. It will be optimized away, but will be visible in the dumps 7254seen via @ref{66,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} 7255and @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, 7256and thus may be of use when debugging how your project’s internal 7257representation gets converted to the libgccjit IR. 7258 7259The parameter @code{text} must be non-NULL. It is copied, so the input 7260buffer does not need to outlive the call. For example: 7261 7262@example 7263char buf[100]; 7264snprintf (buf, sizeof (buf), 7265 "op%i: %s", 7266 pc, opcode_names[op->op_opcode]); 7267gcc_jit_block_add_comment (block, loc, buf); 7268@end example 7269@end deffn 7270 7271@geindex gcc_jit_block_end_with_conditional (C function) 7272@anchor{topics/functions c gcc_jit_block_end_with_conditional}@anchor{2d} 7273@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) 7274 7275Terminate a block by adding evaluation of an rvalue, branching on the 7276result to the appropriate successor block. 7277 7278This is roughly equivalent to this C code: 7279 7280@example 7281if (boolval) 7282 goto on_true; 7283else 7284 goto on_false; 7285@end example 7286 7287block, boolval, on_true, and on_false must be non-NULL. 7288@end deffn 7289 7290@geindex gcc_jit_block_end_with_jump (C function) 7291@anchor{topics/functions c gcc_jit_block_end_with_jump}@anchor{e9} 7292@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) 7293 7294Terminate a block by adding a jump to the given target block. 7295 7296This is roughly equivalent to this C code: 7297 7298@example 7299goto target; 7300@end example 7301@end deffn 7302 7303@geindex gcc_jit_block_end_with_return (C function) 7304@anchor{topics/functions c gcc_jit_block_end_with_return}@anchor{ea} 7305@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) 7306 7307Terminate a block by adding evaluation of an rvalue, returning the value. 7308 7309This is roughly equivalent to this C code: 7310 7311@example 7312return expression; 7313@end example 7314@end deffn 7315 7316@geindex gcc_jit_block_end_with_void_return (C function) 7317@anchor{topics/functions c gcc_jit_block_end_with_void_return}@anchor{eb} 7318@deffn {C Function} void gcc_jit_block_end_with_void_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc) 7319 7320Terminate a block by adding a valueless return, for use within a function 7321with “void” return type. 7322 7323This is equivalent to this C code: 7324 7325@example 7326return; 7327@end example 7328@end deffn 7329 7330@geindex gcc_jit_block_end_with_switch (C function) 7331@anchor{topics/functions c gcc_jit_block_end_with_switch}@anchor{ec} 7332@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) 7333 7334Terminate a block by adding evalation of an rvalue, then performing 7335a multiway branch. 7336 7337This is roughly equivalent to this C code: 7338 7339@example 7340switch (expr) 7341 @{ 7342 default: 7343 goto default_block; 7344 7345 case C0.min_value ... C0.max_value: 7346 goto C0.dest_block; 7347 7348 case C1.min_value ... C1.max_value: 7349 goto C1.dest_block; 7350 7351 ...etc... 7352 7353 case C[N - 1].min_value ... C[N - 1].max_value: 7354 goto C[N - 1].dest_block; 7355@} 7356@end example 7357 7358@code{block}, @code{expr}, @code{default_block} and @code{cases} must all be 7359non-NULL. 7360 7361@code{expr} must be of the same integer type as all of the @code{min_value} 7362and @code{max_value} within the cases. 7363 7364@code{num_cases} must be >= 0. 7365 7366The ranges of the cases must not overlap (or have duplicate 7367values). 7368 7369The API entrypoints relating to switch statements and cases: 7370 7371@quotation 7372 7373 7374@itemize * 7375 7376@item 7377@ref{ec,,gcc_jit_block_end_with_switch()} 7378 7379@item 7380@ref{ed,,gcc_jit_case_as_object()} 7381 7382@item 7383@ref{ee,,gcc_jit_context_new_case()} 7384@end itemize 7385@end quotation 7386 7387were added in @ref{ef,,LIBGCCJIT_ABI_3}; you can test for their presence 7388using 7389 7390@example 7391#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS 7392@end example 7393 7394@geindex gcc_jit_case (C type) 7395@anchor{topics/functions c gcc_jit_case}@anchor{f0} 7396@deffn {C Type} gcc_jit_case 7397@end deffn 7398 7399A @cite{gcc_jit_case} represents a case within a switch statement, and 7400is created within a particular @ref{8,,gcc_jit_context} using 7401@ref{ee,,gcc_jit_context_new_case()}. 7402 7403Each case expresses a multivalued range of integer values. You 7404can express single-valued cases by passing in the same value for 7405both @cite{min_value} and @cite{max_value}. 7406 7407@geindex gcc_jit_context_new_case (C function) 7408@anchor{topics/functions c gcc_jit_context_new_case}@anchor{ee} 7409@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) 7410 7411Create a new gcc_jit_case instance for use in a switch statement. 7412@cite{min_value} and @cite{max_value} must be constants of an integer type, 7413which must match that of the expression of the switch statement. 7414 7415@cite{dest_block} must be within the same function as the switch 7416statement. 7417@end deffn 7418 7419@geindex gcc_jit_case_as_object (C function) 7420@anchor{topics/functions c gcc_jit_case_as_object}@anchor{ed} 7421@deffn {C Function} gcc_jit_object * gcc_jit_case_as_object (gcc_jit_case@w{ }*case_) 7422 7423Upcast from a case to an object. 7424@end deffn 7425 7426Here’s an example of creating a switch statement: 7427 7428@quotation 7429 7430@example 7431 7432void 7433create_code (gcc_jit_context *ctxt, void *user_data) 7434@{ 7435 /* Let's try to inject the equivalent of: 7436 int 7437 test_switch (int x) 7438 @{ 7439 switch (x) 7440 @{ 7441 case 0 ... 5: 7442 return 3; 7443 7444 case 25 ... 27: 7445 return 4; 7446 7447 case -42 ... -17: 7448 return 83; 7449 7450 case 40: 7451 return 8; 7452 7453 default: 7454 return 10; 7455 @} 7456 @} 7457 */ 7458 gcc_jit_type *t_int = 7459 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 7460 gcc_jit_type *return_type = t_int; 7461 gcc_jit_param *x = 7462 gcc_jit_context_new_param (ctxt, NULL, t_int, "x"); 7463 gcc_jit_param *params[1] = @{x@}; 7464 gcc_jit_function *func = 7465 gcc_jit_context_new_function (ctxt, NULL, 7466 GCC_JIT_FUNCTION_EXPORTED, 7467 return_type, 7468 "test_switch", 7469 1, params, 0); 7470 7471 gcc_jit_block *b_initial = 7472 gcc_jit_function_new_block (func, "initial"); 7473 7474 gcc_jit_block *b_default = 7475 gcc_jit_function_new_block (func, "default"); 7476 gcc_jit_block *b_case_0_5 = 7477 gcc_jit_function_new_block (func, "case_0_5"); 7478 gcc_jit_block *b_case_25_27 = 7479 gcc_jit_function_new_block (func, "case_25_27"); 7480 gcc_jit_block *b_case_m42_m17 = 7481 gcc_jit_function_new_block (func, "case_m42_m17"); 7482 gcc_jit_block *b_case_40 = 7483 gcc_jit_function_new_block (func, "case_40"); 7484 7485 gcc_jit_case *cases[4] = @{ 7486 gcc_jit_context_new_case ( 7487 ctxt, 7488 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0), 7489 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5), 7490 b_case_0_5), 7491 gcc_jit_context_new_case ( 7492 ctxt, 7493 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 25), 7494 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 27), 7495 b_case_25_27), 7496 gcc_jit_context_new_case ( 7497 ctxt, 7498 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -42), 7499 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -17), 7500 b_case_m42_m17), 7501 gcc_jit_context_new_case ( 7502 ctxt, 7503 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40), 7504 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40), 7505 b_case_40) 7506 @}; 7507 gcc_jit_block_end_with_switch ( 7508 b_initial, NULL, 7509 gcc_jit_param_as_rvalue (x), 7510 b_default, 7511 4, cases); 7512 7513 gcc_jit_block_end_with_return ( 7514 b_case_0_5, NULL, 7515 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3)); 7516 gcc_jit_block_end_with_return ( 7517 b_case_25_27, NULL, 7518 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4)); 7519 gcc_jit_block_end_with_return ( 7520 b_case_m42_m17, NULL, 7521 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 83)); 7522 gcc_jit_block_end_with_return ( 7523 b_case_40, NULL, 7524 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 8)); 7525 gcc_jit_block_end_with_return ( 7526 b_default, NULL, 7527 gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10)); 7528@} 7529 7530@end example 7531@end quotation 7532@end deffn 7533 7534See also @ref{f1,,gcc_jit_extended_asm} for entrypoints for adding inline 7535assembler statements to a function. 7536 7537@c Copyright (C) 2017-2021 Free Software Foundation, Inc. 7538@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 7539@c 7540@c This is free software: you can redistribute it and/or modify it 7541@c under the terms of the GNU General Public License as published by 7542@c the Free Software Foundation, either version 3 of the License, or 7543@c (at your option) any later version. 7544@c 7545@c This program is distributed in the hope that it will be useful, but 7546@c WITHOUT ANY WARRANTY; without even the implied warranty of 7547@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7548@c General Public License for more details. 7549@c 7550@c You should have received a copy of the GNU General Public License 7551@c along with this program. If not, see 7552@c <http://www.gnu.org/licenses/>. 7553 7554@node Function pointers<2>,Source Locations,Creating and using functions,Topic Reference 7555@anchor{topics/function-pointers doc}@anchor{f2}@anchor{topics/function-pointers function-pointers}@anchor{f3} 7556@section Function pointers 7557 7558 7559You can generate calls that use a function pointer via 7560@ref{bc,,gcc_jit_context_new_call_through_ptr()}. 7561 7562To do requires a @ref{13,,gcc_jit_rvalue} of the correct function pointer type. 7563 7564Function pointers for a @ref{29,,gcc_jit_function} can be obtained 7565via @ref{c0,,gcc_jit_function_get_address()}. 7566 7567@geindex gcc_jit_function_get_address (C function) 7568@anchor{topics/function-pointers c gcc_jit_function_get_address}@anchor{c0} 7569@deffn {C Function} gcc_jit_rvalue * gcc_jit_function_get_address (gcc_jit_function@w{ }*fn, gcc_jit_location@w{ }*loc) 7570 7571Get the address of a function as an rvalue, of function pointer 7572type. 7573 7574This entrypoint was added in @ref{f4,,LIBGCCJIT_ABI_9}; you can test 7575for its presence using 7576 7577@example 7578#ifdef LIBGCCJIT_HAVE_gcc_jit_function_get_address 7579@end example 7580@end deffn 7581 7582Alternatively, given an existing function, you can obtain a pointer 7583to it in @ref{13,,gcc_jit_rvalue} form using 7584@ref{9c,,gcc_jit_context_new_rvalue_from_ptr()}, using a function pointer 7585type obtained using @ref{95,,gcc_jit_context_new_function_ptr_type()}. 7586 7587Here’s an example of creating a function pointer type corresponding to C’s 7588@code{void (*) (int, int, int)}: 7589 7590@example 7591gcc_jit_type *void_type = 7592 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); 7593gcc_jit_type *int_type = 7594 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 7595 7596/* Build the function ptr type. */ 7597gcc_jit_type *param_types[3]; 7598param_types[0] = int_type; 7599param_types[1] = int_type; 7600param_types[2] = int_type; 7601 7602gcc_jit_type *fn_ptr_type = 7603 gcc_jit_context_new_function_ptr_type (ctxt, NULL, 7604 void_type, 7605 3, param_types, 0); 7606@end example 7607 7608@geindex gcc_jit_context_new_function_ptr_type (C function) 7609@anchor{topics/function-pointers c gcc_jit_context_new_function_ptr_type}@anchor{95} 7610@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) 7611 7612Generate a @ref{a,,gcc_jit_type} for a function pointer with the 7613given return type and parameters. 7614 7615Each of @cite{param_types} must be non-@cite{void}; @cite{return_type} may be @cite{void}. 7616@end deffn 7617 7618@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 7619@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 7620@c 7621@c This is free software: you can redistribute it and/or modify it 7622@c under the terms of the GNU General Public License as published by 7623@c the Free Software Foundation, either version 3 of the License, or 7624@c (at your option) any later version. 7625@c 7626@c This program is distributed in the hope that it will be useful, but 7627@c WITHOUT ANY WARRANTY; without even the implied warranty of 7628@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7629@c General Public License for more details. 7630@c 7631@c You should have received a copy of the GNU General Public License 7632@c along with this program. If not, see 7633@c <http://www.gnu.org/licenses/>. 7634 7635@node Source Locations,Compiling a context,Function pointers<2>,Topic Reference 7636@anchor{topics/locations doc}@anchor{f5}@anchor{topics/locations source-locations}@anchor{f6} 7637@section Source Locations 7638 7639 7640@geindex gcc_jit_location (C type) 7641@anchor{topics/locations c gcc_jit_location}@anchor{3b} 7642@deffn {C Type} gcc_jit_location 7643 7644A @cite{gcc_jit_location} encapsulates a source code location, so that 7645you can (optionally) associate locations in your language with 7646statements in the JIT-compiled code, allowing the debugger to 7647single-step through your language. 7648 7649@cite{gcc_jit_location} instances are optional: you can always pass NULL to 7650any API entrypoint accepting one. 7651 7652You can construct them using @ref{41,,gcc_jit_context_new_location()}. 7653 7654You need to enable @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 7655@ref{8,,gcc_jit_context} for these locations to actually be usable by 7656the debugger: 7657 7658@example 7659gcc_jit_context_set_bool_option ( 7660 ctxt, 7661 GCC_JIT_BOOL_OPTION_DEBUGINFO, 7662 1); 7663@end example 7664@end deffn 7665 7666@geindex gcc_jit_context_new_location (C function) 7667@anchor{topics/locations c gcc_jit_context_new_location}@anchor{41} 7668@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) 7669 7670Create a @cite{gcc_jit_location} instance representing the given source 7671location. 7672 7673The parameter @code{filename} must be non-NULL. The call takes a copy of 7674the underlying string, so it is valid to pass in a pointer to an 7675on-stack buffer. 7676@end deffn 7677 7678@menu 7679* Faking it:: 7680 7681@end menu 7682 7683@node Faking it,,,Source Locations 7684@anchor{topics/locations faking-it}@anchor{f7} 7685@subsection Faking it 7686 7687 7688If you don’t have source code for your internal representation, but need 7689to debug, you can generate a C-like representation of the functions in 7690your context using @ref{5a,,gcc_jit_context_dump_to_file()}: 7691 7692@example 7693gcc_jit_context_dump_to_file (ctxt, "/tmp/something.c", 7694 1 /* update_locations */); 7695@end example 7696 7697This will dump C-like code to the given path. If the @cite{update_locations} 7698argument is true, this will also set up @cite{gcc_jit_location} information 7699throughout the context, pointing at the dump file as if it were a source 7700file, giving you @emph{something} you can step through in the debugger. 7701 7702@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 7703@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 7704@c 7705@c This is free software: you can redistribute it and/or modify it 7706@c under the terms of the GNU General Public License as published by 7707@c the Free Software Foundation, either version 3 of the License, or 7708@c (at your option) any later version. 7709@c 7710@c This program is distributed in the hope that it will be useful, but 7711@c WITHOUT ANY WARRANTY; without even the implied warranty of 7712@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7713@c General Public License for more details. 7714@c 7715@c You should have received a copy of the GNU General Public License 7716@c along with this program. If not, see 7717@c <http://www.gnu.org/licenses/>. 7718 7719@node Compiling a context,ABI and API compatibility,Source Locations,Topic Reference 7720@anchor{topics/compilation doc}@anchor{f8}@anchor{topics/compilation compiling-a-context}@anchor{f9} 7721@section Compiling a context 7722 7723 7724Once populated, a @ref{8,,gcc_jit_context *} can be compiled to 7725machine code, either in-memory via @ref{15,,gcc_jit_context_compile()} or 7726to disk via @ref{4a,,gcc_jit_context_compile_to_file()}. 7727 7728You can compile a context multiple times (using either form of 7729compilation), although any errors that occur on the context will 7730prevent any future compilation of that context. 7731 7732@menu 7733* In-memory compilation:: 7734* Ahead-of-time compilation:: 7735 7736@end menu 7737 7738@node In-memory compilation,Ahead-of-time compilation,,Compiling a context 7739@anchor{topics/compilation in-memory-compilation}@anchor{fa} 7740@subsection In-memory compilation 7741 7742 7743@geindex gcc_jit_context_compile (C function) 7744@anchor{topics/compilation c gcc_jit_context_compile}@anchor{15} 7745@deffn {C Function} gcc_jit_result * gcc_jit_context_compile (gcc_jit_context@w{ }*ctxt) 7746 7747This calls into GCC and builds the code, returning a 7748@cite{gcc_jit_result *}. 7749 7750If the result is non-NULL, the caller becomes responsible for 7751calling @ref{39,,gcc_jit_result_release()} on it once they’re done 7752with it. 7753@end deffn 7754 7755@geindex gcc_jit_result (C type) 7756@anchor{topics/compilation c gcc_jit_result}@anchor{16} 7757@deffn {C Type} gcc_jit_result 7758 7759A @cite{gcc_jit_result} encapsulates the result of compiling a context 7760in-memory, and the lifetimes of any machine code functions or globals 7761that are within the result. 7762@end deffn 7763 7764@geindex gcc_jit_result_get_code (C function) 7765@anchor{topics/compilation c gcc_jit_result_get_code}@anchor{17} 7766@deffn {C Function} void * gcc_jit_result_get_code (gcc_jit_result@w{ }*result, const char@w{ }*funcname) 7767 7768Locate a given function within the built machine code. 7769 7770Functions are looked up by name. For this to succeed, a function 7771with a name matching @cite{funcname} must have been created on 7772@cite{result}’s context (or a parent context) via a call to 7773@ref{11,,gcc_jit_context_new_function()} with @cite{kind} 7774@ref{dd,,GCC_JIT_FUNCTION_EXPORTED}: 7775 7776@example 7777gcc_jit_context_new_function (ctxt, 7778 any_location, /* or NULL */ 7779 /* Required for func to be visible to 7780 gcc_jit_result_get_code: */ 7781 GCC_JIT_FUNCTION_EXPORTED, 7782 any_return_type, 7783 /* Must string-compare equal: */ 7784 funcname, 7785 /* etc */); 7786@end example 7787 7788If such a function is not found (or @cite{result} or @cite{funcname} are 7789@code{NULL}), an error message will be emitted on stderr and 7790@code{NULL} will be returned. 7791 7792If the function is found, the result will need to be cast to a 7793function pointer of the correct type before it can be called. 7794 7795Note that the resulting machine code becomes invalid after 7796@ref{39,,gcc_jit_result_release()} is called on the 7797@ref{16,,gcc_jit_result *}; attempting to call it after that may lead 7798to a segmentation fault. 7799@end deffn 7800 7801@geindex gcc_jit_result_get_global (C function) 7802@anchor{topics/compilation c gcc_jit_result_get_global}@anchor{cb} 7803@deffn {C Function} void * gcc_jit_result_get_global (gcc_jit_result@w{ }*result, const char@w{ }*name) 7804 7805Locate a given global within the built machine code. 7806 7807Globals are looked up by name. For this to succeed, a global 7808with a name matching @cite{name} must have been created on 7809@cite{result}’s context (or a parent context) via a call to 7810@ref{c8,,gcc_jit_context_new_global()} with @cite{kind} 7811@ref{ca,,GCC_JIT_GLOBAL_EXPORTED}. 7812 7813If the global is found, the result will need to be cast to a 7814pointer of the correct type before it can be called. 7815 7816This is a @emph{pointer} to the global, so e.g. for an @code{int} this is 7817an @code{int *}. 7818 7819For example, given an @code{int foo;} created this way: 7820 7821@example 7822gcc_jit_lvalue *exported_global = 7823 gcc_jit_context_new_global (ctxt, 7824 any_location, /* or NULL */ 7825 GCC_JIT_GLOBAL_EXPORTED, 7826 int_type, 7827 "foo"); 7828@end example 7829 7830we can access it like this: 7831 7832@example 7833int *ptr_to_foo = 7834 (int *)gcc_jit_result_get_global (result, "foo"); 7835@end example 7836 7837If such a global is not found (or @cite{result} or @cite{name} are 7838@code{NULL}), an error message will be emitted on stderr and 7839@code{NULL} will be returned. 7840 7841Note that the resulting address becomes invalid after 7842@ref{39,,gcc_jit_result_release()} is called on the 7843@ref{16,,gcc_jit_result *}; attempting to use it after that may lead 7844to a segmentation fault. 7845@end deffn 7846 7847@geindex gcc_jit_result_release (C function) 7848@anchor{topics/compilation c gcc_jit_result_release}@anchor{39} 7849@deffn {C Function} void gcc_jit_result_release (gcc_jit_result@w{ }*result) 7850 7851Once we’re done with the code, this unloads the built .so file. 7852This cleans up the result; after calling this, it’s no longer 7853valid to use the result, or any code or globals that were obtained 7854by calling @ref{17,,gcc_jit_result_get_code()} or 7855@ref{cb,,gcc_jit_result_get_global()} on it. 7856@end deffn 7857 7858@node Ahead-of-time compilation,,In-memory compilation,Compiling a context 7859@anchor{topics/compilation ahead-of-time-compilation}@anchor{fb} 7860@subsection Ahead-of-time compilation 7861 7862 7863Although libgccjit is primarily aimed at just-in-time compilation, it 7864can also be used for implementing more traditional ahead-of-time 7865compilers, via the @ref{4a,,gcc_jit_context_compile_to_file()} 7866API entrypoint. 7867 7868@geindex gcc_jit_context_compile_to_file (C function) 7869@anchor{topics/compilation c gcc_jit_context_compile_to_file}@anchor{4a} 7870@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) 7871 7872Compile the @ref{8,,gcc_jit_context *} to a file of the given 7873kind. 7874@end deffn 7875 7876@ref{4a,,gcc_jit_context_compile_to_file()} ignores the suffix of 7877@code{output_path}, and insteads uses the given 7878@code{enum gcc_jit_output_kind} to decide what to do. 7879 7880@cartouche 7881@quotation Note 7882This is different from the @code{gcc} program, which does make use of the 7883suffix of the output file when determining what to do. 7884@end quotation 7885@end cartouche 7886 7887@geindex gcc_jit_output_kind (C type) 7888@anchor{topics/compilation c gcc_jit_output_kind}@anchor{fc} 7889@deffn {C Type} enum gcc_jit_output_kind 7890@end deffn 7891 7892The available kinds of output are: 7893 7894 7895@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxx} 7896@headitem 7897 7898Output kind 7899 7900@tab 7901 7902Typical suffix 7903 7904@item 7905 7906@ref{fd,,GCC_JIT_OUTPUT_KIND_ASSEMBLER} 7907 7908@tab 7909 7910.s 7911 7912@item 7913 7914@ref{fe,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE} 7915 7916@tab 7917 7918.o 7919 7920@item 7921 7922@ref{ff,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY} 7923 7924@tab 7925 7926.so or .dll 7927 7928@item 7929 7930@ref{100,,GCC_JIT_OUTPUT_KIND_EXECUTABLE} 7931 7932@tab 7933 7934None, or .exe 7935 7936@end multitable 7937 7938 7939@geindex GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro) 7940@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{fd} 7941@deffn {C Macro} GCC_JIT_OUTPUT_KIND_ASSEMBLER 7942 7943Compile the context to an assembler file. 7944@end deffn 7945 7946@geindex GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro) 7947@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{fe} 7948@deffn {C Macro} GCC_JIT_OUTPUT_KIND_OBJECT_FILE 7949 7950Compile the context to an object file. 7951@end deffn 7952 7953@geindex GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro) 7954@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{ff} 7955@deffn {C Macro} GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY 7956 7957Compile the context to a dynamic library. 7958 7959There is currently no support for specifying other libraries to link 7960against. 7961@end deffn 7962 7963@geindex GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro) 7964@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{100} 7965@deffn {C Macro} GCC_JIT_OUTPUT_KIND_EXECUTABLE 7966 7967Compile the context to an executable. 7968 7969There is currently no support for specifying libraries to link 7970against. 7971@end deffn 7972 7973@c Copyright (C) 2015-2021 Free Software Foundation, Inc. 7974@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 7975@c 7976@c This is free software: you can redistribute it and/or modify it 7977@c under the terms of the GNU General Public License as published by 7978@c the Free Software Foundation, either version 3 of the License, or 7979@c (at your option) any later version. 7980@c 7981@c This program is distributed in the hope that it will be useful, but 7982@c WITHOUT ANY WARRANTY; without even the implied warranty of 7983@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7984@c General Public License for more details. 7985@c 7986@c You should have received a copy of the GNU General Public License 7987@c along with this program. If not, see 7988@c <http://www.gnu.org/licenses/>. 7989 7990@node ABI and API compatibility,Performance,Compiling a context,Topic Reference 7991@anchor{topics/compatibility doc}@anchor{101}@anchor{topics/compatibility abi-and-api-compatibility}@anchor{102} 7992@section ABI and API compatibility 7993 7994 7995The libgccjit developers strive for ABI and API backward-compatibility: 7996programs built against libgccjit.so stand a good chance of running 7997without recompilation against newer versions of libgccjit.so, and 7998ought to recompile without modification against newer versions of 7999libgccjit.h. 8000 8001@cartouche 8002@quotation Note 8003The libgccjit++.h C++ API is more experimental, and less 8004locked-down at this time. 8005@end quotation 8006@end cartouche 8007 8008API compatibility is achieved by extending the API rather than changing 8009it. For ABI compatiblity, we avoid bumping the SONAME, and instead use 8010symbol versioning to tag each symbol, so that a binary linked against 8011libgccjit.so is tagged according to the symbols that it uses. 8012 8013For example, @ref{72,,gcc_jit_context_add_command_line_option()} was added in 8014@code{LIBGCCJIT_ABI_1}. If a client program uses it, this can be detected 8015from metadata by using @code{objdump}: 8016 8017@example 8018$ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8 8019 8020Version References: 8021 required from libgccjit.so.0: 8022 0x00824161 0x00 04 LIBGCCJIT_ABI_1 8023 0x00824160 0x00 03 LIBGCCJIT_ABI_0 8024 required from libc.so.6: 8025@end example 8026 8027You can see the symbol tags provided by libgccjit.so using @code{objdump}: 8028 8029@example 8030$ objdump -p libgccjit.so | less 8031[...snip...] 8032Version definitions: 80331 0x01 0x0ff81f20 libgccjit.so.0 80342 0x00 0x00824160 LIBGCCJIT_ABI_0 80353 0x00 0x00824161 LIBGCCJIT_ABI_1 8036 LIBGCCJIT_ABI_0 8037[...snip...] 8038@end example 8039 8040@menu 8041* Programmatically checking version:: 8042* ABI symbol tags:: 8043 8044@end menu 8045 8046@node Programmatically checking version,ABI symbol tags,,ABI and API compatibility 8047@anchor{topics/compatibility programmatically-checking-version}@anchor{103} 8048@subsection Programmatically checking version 8049 8050 8051Client code can programmatically check libgccjit version using: 8052 8053@geindex gcc_jit_version_major (C function) 8054@anchor{topics/compatibility c gcc_jit_version_major}@anchor{104} 8055@deffn {C Function} int gcc_jit_version_major (void) 8056 8057Return libgccjit major version. This is analogous to __GNUC__ in C code. 8058@end deffn 8059 8060@geindex gcc_jit_version_minor (C function) 8061@anchor{topics/compatibility c gcc_jit_version_minor}@anchor{105} 8062@deffn {C Function} int gcc_jit_version_minor (void) 8063 8064Return libgccjit minor version. This is analogous to 8065__GNUC_MINOR__ in C code. 8066@end deffn 8067 8068@geindex gcc_jit_version_patchlevel (C function) 8069@anchor{topics/compatibility c gcc_jit_version_patchlevel}@anchor{106} 8070@deffn {C Function} int gcc_jit_version_patchlevel (void) 8071 8072Return libgccjit patchlevel version. This is analogous to 8073__GNUC_PATCHLEVEL__ in C code. 8074@end deffn 8075 8076@cartouche 8077@quotation Note 8078These entry points has been added with @code{LIBGCCJIT_ABI_13} 8079(see below). 8080@end quotation 8081@end cartouche 8082 8083@node ABI symbol tags,,Programmatically checking version,ABI and API compatibility 8084@anchor{topics/compatibility abi-symbol-tags}@anchor{107} 8085@subsection ABI symbol tags 8086 8087 8088The initial release of libgccjit (in gcc 5.1) did not use symbol versioning. 8089 8090Newer releases use the following tags. 8091 8092@menu 8093* LIBGCCJIT_ABI_0:: 8094* LIBGCCJIT_ABI_1:: 8095* LIBGCCJIT_ABI_2:: 8096* LIBGCCJIT_ABI_3:: 8097* LIBGCCJIT_ABI_4:: 8098* LIBGCCJIT_ABI_5:: 8099* LIBGCCJIT_ABI_6:: 8100* LIBGCCJIT_ABI_7:: 8101* LIBGCCJIT_ABI_8:: 8102* LIBGCCJIT_ABI_9:: 8103* LIBGCCJIT_ABI_10:: 8104* LIBGCCJIT_ABI_11:: 8105* LIBGCCJIT_ABI_12:: 8106* LIBGCCJIT_ABI_13:: 8107* LIBGCCJIT_ABI_14:: 8108* LIBGCCJIT_ABI_15:: 8109 8110@end menu 8111 8112@node LIBGCCJIT_ABI_0,LIBGCCJIT_ABI_1,,ABI symbol tags 8113@anchor{topics/compatibility id1}@anchor{108}@anchor{topics/compatibility libgccjit-abi-0}@anchor{109} 8114@subsubsection @code{LIBGCCJIT_ABI_0} 8115 8116 8117All entrypoints in the initial release of libgccjit are tagged with 8118@code{LIBGCCJIT_ABI_0}, to signify the transition to symbol versioning. 8119 8120Binaries built against older copies of @code{libgccjit.so} should 8121continue to work, with this being handled transparently by the linker 8122(see this post@footnote{https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html}) 8123 8124@node LIBGCCJIT_ABI_1,LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_0,ABI symbol tags 8125@anchor{topics/compatibility id2}@anchor{10a}@anchor{topics/compatibility libgccjit-abi-1}@anchor{73} 8126@subsubsection @code{LIBGCCJIT_ABI_1} 8127 8128 8129@code{LIBGCCJIT_ABI_1} covers the addition of 8130@ref{72,,gcc_jit_context_add_command_line_option()} 8131 8132@node LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_1,ABI symbol tags 8133@anchor{topics/compatibility id3}@anchor{10b}@anchor{topics/compatibility libgccjit-abi-2}@anchor{6c} 8134@subsubsection @code{LIBGCCJIT_ABI_2} 8135 8136 8137@code{LIBGCCJIT_ABI_2} covers the addition of 8138@ref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()} 8139 8140@node LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_2,ABI symbol tags 8141@anchor{topics/compatibility id4}@anchor{10c}@anchor{topics/compatibility libgccjit-abi-3}@anchor{ef} 8142@subsubsection @code{LIBGCCJIT_ABI_3} 8143 8144 8145@code{LIBGCCJIT_ABI_3} covers the addition of switch statements via API 8146entrypoints: 8147 8148@quotation 8149 8150 8151@itemize * 8152 8153@item 8154@ref{ec,,gcc_jit_block_end_with_switch()} 8155 8156@item 8157@ref{ed,,gcc_jit_case_as_object()} 8158 8159@item 8160@ref{ee,,gcc_jit_context_new_case()} 8161@end itemize 8162@end quotation 8163 8164@node LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_3,ABI symbol tags 8165@anchor{topics/compatibility id5}@anchor{10d}@anchor{topics/compatibility libgccjit-abi-4}@anchor{10e} 8166@subsubsection @code{LIBGCCJIT_ABI_4} 8167 8168 8169@code{LIBGCCJIT_ABI_4} covers the addition of timers via API 8170entrypoints: 8171 8172@quotation 8173 8174 8175@itemize * 8176 8177@item 8178@ref{10f,,gcc_jit_context_get_timer()} 8179 8180@item 8181@ref{110,,gcc_jit_context_set_timer()} 8182 8183@item 8184@ref{111,,gcc_jit_timer_new()} 8185 8186@item 8187@ref{112,,gcc_jit_timer_release()} 8188 8189@item 8190@ref{113,,gcc_jit_timer_push()} 8191 8192@item 8193@ref{114,,gcc_jit_timer_pop()} 8194 8195@item 8196@ref{115,,gcc_jit_timer_print()} 8197@end itemize 8198@end quotation 8199 8200@node LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_4,ABI symbol tags 8201@anchor{topics/compatibility id6}@anchor{116}@anchor{topics/compatibility libgccjit-abi-5}@anchor{6e} 8202@subsubsection @code{LIBGCCJIT_ABI_5} 8203 8204 8205@code{LIBGCCJIT_ABI_5} covers the addition of 8206@ref{6d,,gcc_jit_context_set_bool_use_external_driver()} 8207 8208@node LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_5,ABI symbol tags 8209@anchor{topics/compatibility id7}@anchor{117}@anchor{topics/compatibility libgccjit-abi-6}@anchor{be} 8210@subsubsection @code{LIBGCCJIT_ABI_6} 8211 8212 8213@code{LIBGCCJIT_ABI_6} covers the addition of 8214@ref{bd,,gcc_jit_rvalue_set_bool_require_tail_call()} 8215 8216@node LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_6,ABI symbol tags 8217@anchor{topics/compatibility id8}@anchor{118}@anchor{topics/compatibility libgccjit-abi-7}@anchor{83} 8218@subsubsection @code{LIBGCCJIT_ABI_7} 8219 8220 8221@code{LIBGCCJIT_ABI_7} covers the addition of 8222@ref{82,,gcc_jit_type_get_aligned()} 8223 8224@node LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_7,ABI symbol tags 8225@anchor{topics/compatibility id9}@anchor{119}@anchor{topics/compatibility libgccjit-abi-8}@anchor{86} 8226@subsubsection @code{LIBGCCJIT_ABI_8} 8227 8228 8229@code{LIBGCCJIT_ABI_8} covers the addition of 8230@ref{85,,gcc_jit_type_get_vector()} 8231 8232@node LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_8,ABI symbol tags 8233@anchor{topics/compatibility id10}@anchor{11a}@anchor{topics/compatibility libgccjit-abi-9}@anchor{f4} 8234@subsubsection @code{LIBGCCJIT_ABI_9} 8235 8236 8237@code{LIBGCCJIT_ABI_9} covers the addition of 8238@ref{c0,,gcc_jit_function_get_address()} 8239 8240@node LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_9,ABI symbol tags 8241@anchor{topics/compatibility id11}@anchor{11b}@anchor{topics/compatibility libgccjit-abi-10}@anchor{a0} 8242@subsubsection @code{LIBGCCJIT_ABI_10} 8243 8244 8245@code{LIBGCCJIT_ABI_10} covers the addition of 8246@ref{87,,gcc_jit_context_new_rvalue_from_vector()} 8247 8248@node LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_10,ABI symbol tags 8249@anchor{topics/compatibility id12}@anchor{11c}@anchor{topics/compatibility libgccjit-abi-11}@anchor{75} 8250@subsubsection @code{LIBGCCJIT_ABI_11} 8251 8252 8253@code{LIBGCCJIT_ABI_11} covers the addition of 8254@ref{74,,gcc_jit_context_add_driver_option()} 8255 8256@node LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_11,ABI symbol tags 8257@anchor{topics/compatibility id13}@anchor{11d}@anchor{topics/compatibility libgccjit-abi-12}@anchor{8d} 8258@subsubsection @code{LIBGCCJIT_ABI_12} 8259 8260 8261@code{LIBGCCJIT_ABI_12} covers the addition of 8262@ref{8c,,gcc_jit_context_new_bitfield()} 8263 8264@node LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_12,ABI symbol tags 8265@anchor{topics/compatibility id14}@anchor{11e}@anchor{topics/compatibility libgccjit-abi-13}@anchor{11f} 8266@subsubsection @code{LIBGCCJIT_ABI_13} 8267 8268 8269@code{LIBGCCJIT_ABI_13} covers the addition of version functions via API 8270entrypoints: 8271 8272@quotation 8273 8274 8275@itemize * 8276 8277@item 8278@ref{104,,gcc_jit_version_major()} 8279 8280@item 8281@ref{105,,gcc_jit_version_minor()} 8282 8283@item 8284@ref{106,,gcc_jit_version_patchlevel()} 8285@end itemize 8286@end quotation 8287 8288@node LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_15,LIBGCCJIT_ABI_13,ABI symbol tags 8289@anchor{topics/compatibility id15}@anchor{120}@anchor{topics/compatibility libgccjit-abi-14}@anchor{cf} 8290@subsubsection @code{LIBGCCJIT_ABI_14} 8291 8292 8293@code{LIBGCCJIT_ABI_14} covers the addition of 8294@ref{ce,,gcc_jit_global_set_initializer()} 8295 8296@node LIBGCCJIT_ABI_15,,LIBGCCJIT_ABI_14,ABI symbol tags 8297@anchor{topics/compatibility id16}@anchor{121}@anchor{topics/compatibility libgccjit-abi-15}@anchor{122} 8298@subsubsection @code{LIBGCCJIT_ABI_15} 8299 8300 8301@code{LIBGCCJIT_ABI_15} covers the addition of API entrypoints for directly 8302embedding assembler instructions: 8303 8304@quotation 8305 8306 8307@itemize * 8308 8309@item 8310@ref{123,,gcc_jit_block_add_extended_asm()} 8311 8312@item 8313@ref{124,,gcc_jit_block_end_with_extended_asm_goto()} 8314 8315@item 8316@ref{125,,gcc_jit_extended_asm_as_object()} 8317 8318@item 8319@ref{126,,gcc_jit_extended_asm_set_volatile_flag()} 8320 8321@item 8322@ref{127,,gcc_jit_extended_asm_set_inline_flag()} 8323 8324@item 8325@ref{128,,gcc_jit_extended_asm_add_output_operand()} 8326 8327@item 8328@ref{129,,gcc_jit_extended_asm_add_input_operand()} 8329 8330@item 8331@ref{12a,,gcc_jit_extended_asm_add_clobber()} 8332 8333@item 8334@ref{12b,,gcc_jit_context_add_top_level_asm()} 8335@end itemize 8336@end quotation 8337 8338@c Copyright (C) 2015-2021 Free Software Foundation, Inc. 8339@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 8340@c 8341@c This is free software: you can redistribute it and/or modify it 8342@c under the terms of the GNU General Public License as published by 8343@c the Free Software Foundation, either version 3 of the License, or 8344@c (at your option) any later version. 8345@c 8346@c This program is distributed in the hope that it will be useful, but 8347@c WITHOUT ANY WARRANTY; without even the implied warranty of 8348@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8349@c General Public License for more details. 8350@c 8351@c You should have received a copy of the GNU General Public License 8352@c along with this program. If not, see 8353@c <http://www.gnu.org/licenses/>. 8354 8355@node Performance,Using Assembly Language with libgccjit,ABI and API compatibility,Topic Reference 8356@anchor{topics/performance doc}@anchor{12c}@anchor{topics/performance performance}@anchor{12d} 8357@section Performance 8358 8359 8360@menu 8361* The timing API:: 8362 8363@end menu 8364 8365@node The timing API,,,Performance 8366@anchor{topics/performance the-timing-api}@anchor{12e} 8367@subsection The timing API 8368 8369 8370As of GCC 6, libgccjit exposes a timing API, for printing reports on 8371how long was spent in different parts of code. 8372 8373You can create a @ref{12f,,gcc_jit_timer} instance, which will 8374measure time spent since its creation. The timer maintains a stack 8375of “timer items”: as control flow moves through your code, you can push 8376and pop named items relating to your code onto the stack, and the timer 8377will account the time spent accordingly. 8378 8379You can also asssociate a timer with a @ref{8,,gcc_jit_context}, in 8380which case the time spent inside compilation will be subdivided. 8381 8382For example, the following code uses a timer, recording client items 8383“create_code”, “compile”, and “running code”: 8384 8385@example 8386/* Create a timer. */ 8387gcc_jit_timer *timer = gcc_jit_timer_new (); 8388if (!timer) 8389 @{ 8390 error ("gcc_jit_timer_new failed"); 8391 return -1; 8392 @} 8393 8394/* Let's repeatedly compile and run some code, accumulating it 8395 all into the timer. */ 8396for (int i = 0; i < num_iterations; i++) 8397 @{ 8398 /* Create a context and associate it with the timer. */ 8399 gcc_jit_context *ctxt = gcc_jit_context_acquire (); 8400 if (!ctxt) 8401 @{ 8402 error ("gcc_jit_context_acquire failed"); 8403 return -1; 8404 @} 8405 gcc_jit_context_set_timer (ctxt, timer); 8406 8407 /* Populate the context, timing it as client item "create_code". */ 8408 gcc_jit_timer_push (timer, "create_code"); 8409 create_code (ctxt); 8410 gcc_jit_timer_pop (timer, "create_code"); 8411 8412 /* Compile the context, timing it as client item "compile". */ 8413 gcc_jit_timer_push (timer, "compile"); 8414 result = gcc_jit_context_compile (ctxt); 8415 gcc_jit_timer_pop (timer, "compile"); 8416 8417 /* Run the generated code, timing it as client item "running code". */ 8418 gcc_jit_timer_push (timer, "running code"); 8419 run_the_code (ctxt, result); 8420 gcc_jit_timer_pop (timer, "running code"); 8421 8422 /* Clean up. */ 8423 gcc_jit_context_release (ctxt); 8424 gcc_jit_result_release (result); 8425@} 8426 8427/* Print the accumulated timings. */ 8428gcc_jit_timer_print (timer, stderr); 8429gcc_jit_timer_release (timer); 8430@end example 8431 8432giving output like this, showing the internal GCC items at the top, then 8433client items, then the total: 8434 8435@example 8436Execution times (seconds) 8437GCC items: 8438 phase setup : 0.29 (14%) usr 0.00 ( 0%) sys 0.32 ( 5%) wall 10661 kB (50%) ggc 8439 phase parsing : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 653 kB ( 3%) ggc 8440 phase finalize : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8441 dump files : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 8442 callgraph construction : 0.02 ( 1%) usr 0.01 ( 6%) sys 0.01 ( 0%) wall 242 kB ( 1%) ggc 8443 callgraph optimization : 0.03 ( 2%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 142 kB ( 1%) ggc 8444 trivially dead code : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8445 df scan insns : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 9 kB ( 0%) ggc 8446 df live regs : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 8447 inline parameters : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 82 kB ( 0%) ggc 8448 tree CFG cleanup : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8449 tree PHI insertion : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 64 kB ( 0%) ggc 8450 tree SSA other : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 18 kB ( 0%) ggc 8451 expand : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 398 kB ( 2%) ggc 8452 jump : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8453 loop init : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 67 kB ( 0%) ggc 8454 integrated RA : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 2468 kB (12%) ggc 8455 thread pro- & epilogue : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 162 kB ( 1%) ggc 8456 final : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 216 kB ( 1%) ggc 8457 rest of compilation : 1.37 (69%) usr 0.00 ( 0%) sys 1.13 (18%) wall 1391 kB ( 6%) ggc 8458 assemble JIT code : 0.01 ( 1%) usr 0.00 ( 0%) sys 4.04 (66%) wall 0 kB ( 0%) ggc 8459 load JIT result : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8460 JIT client code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8461Client items: 8462 create_code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8463 compile : 0.36 (18%) usr 0.15 (83%) sys 0.86 (14%) wall 14939 kB (70%) ggc 8464 running code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 8465 TOTAL : 2.00 0.18 6.12 21444 kB 8466@end example 8467 8468The exact format is intended to be human-readable, and is subject to change. 8469 8470@geindex LIBGCCJIT_HAVE_TIMING_API (C macro) 8471@anchor{topics/performance c LIBGCCJIT_HAVE_TIMING_API}@anchor{130} 8472@deffn {C Macro} LIBGCCJIT_HAVE_TIMING_API 8473 8474The timer API was added to libgccjit in GCC 6. 8475This macro is only defined in versions of libgccjit.h which have the 8476timer API, and so can be used to guard code that may need to compile 8477against earlier releases: 8478 8479@example 8480#ifdef LIBGCCJIT_HAVE_TIMING_API 8481gcc_jit_timer *t = gcc_jit_timer_new (); 8482gcc_jit_context_set_timer (ctxt, t); 8483#endif 8484@end example 8485@end deffn 8486 8487@geindex gcc_jit_timer (C type) 8488@anchor{topics/performance c gcc_jit_timer}@anchor{12f} 8489@deffn {C Type} gcc_jit_timer 8490@end deffn 8491 8492@geindex gcc_jit_timer_new (C function) 8493@anchor{topics/performance c gcc_jit_timer_new}@anchor{111} 8494@deffn {C Function} gcc_jit_timer * gcc_jit_timer_new (void) 8495 8496Create a @ref{12f,,gcc_jit_timer} instance, and start timing: 8497 8498@example 8499gcc_jit_timer *t = gcc_jit_timer_new (); 8500@end example 8501 8502This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8503for its presence using 8504 8505@example 8506#ifdef LIBGCCJIT_HAVE_TIMING_API 8507@end example 8508@end deffn 8509 8510@geindex gcc_jit_timer_release (C function) 8511@anchor{topics/performance c gcc_jit_timer_release}@anchor{112} 8512@deffn {C Function} void gcc_jit_timer_release (gcc_jit_timer@w{ }*timer) 8513 8514Release a @ref{12f,,gcc_jit_timer} instance: 8515 8516@example 8517gcc_jit_timer_release (t); 8518@end example 8519 8520This should be called exactly once on a timer. 8521 8522This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8523for its presence using 8524 8525@example 8526#ifdef LIBGCCJIT_HAVE_TIMING_API 8527@end example 8528@end deffn 8529 8530@geindex gcc_jit_context_set_timer (C function) 8531@anchor{topics/performance c gcc_jit_context_set_timer}@anchor{110} 8532@deffn {C Function} void gcc_jit_context_set_timer (gcc_jit_context@w{ }*ctxt, gcc_jit_timer@w{ }*timer) 8533 8534Associate a @ref{12f,,gcc_jit_timer} instance with a context: 8535 8536@example 8537gcc_jit_context_set_timer (ctxt, t); 8538@end example 8539 8540A timer instance can be shared between multiple 8541@ref{8,,gcc_jit_context} instances. 8542 8543Timers have no locking, so if you have a multithreaded program, you 8544must provide your own locks if more than one thread could be working 8545with the same timer via timer-associated contexts. 8546 8547This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8548for its presence using 8549 8550@example 8551#ifdef LIBGCCJIT_HAVE_TIMING_API 8552@end example 8553@end deffn 8554 8555@geindex gcc_jit_context_get_timer (C function) 8556@anchor{topics/performance c gcc_jit_context_get_timer}@anchor{10f} 8557@deffn {C Function} gcc_jit_timer *gcc_jit_context_get_timer (gcc_jit_context@w{ }*ctxt) 8558 8559Get the timer associated with a context (if any). 8560 8561This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8562for its presence using 8563 8564@example 8565#ifdef LIBGCCJIT_HAVE_TIMING_API 8566@end example 8567@end deffn 8568 8569@geindex gcc_jit_timer_push (C function) 8570@anchor{topics/performance c gcc_jit_timer_push}@anchor{113} 8571@deffn {C Function} void gcc_jit_timer_push (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name) 8572 8573Push the given item onto the timer’s stack: 8574 8575@example 8576gcc_jit_timer_push (t, "running code"); 8577run_the_code (ctxt, result); 8578gcc_jit_timer_pop (t, "running code"); 8579@end example 8580 8581This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8582for its presence using 8583 8584@example 8585#ifdef LIBGCCJIT_HAVE_TIMING_API 8586@end example 8587@end deffn 8588 8589@geindex gcc_jit_timer_pop (C function) 8590@anchor{topics/performance c gcc_jit_timer_pop}@anchor{114} 8591@deffn {C Function} void gcc_jit_timer_pop (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name) 8592 8593Pop the top item from the timer’s stack. 8594 8595If “item_name” is provided, it must match that of the top item. 8596Alternatively, @code{NULL} can be passed in, to suppress checking. 8597 8598This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8599for its presence using 8600 8601@example 8602#ifdef LIBGCCJIT_HAVE_TIMING_API 8603@end example 8604@end deffn 8605 8606@geindex gcc_jit_timer_print (C function) 8607@anchor{topics/performance c gcc_jit_timer_print}@anchor{115} 8608@deffn {C Function} void gcc_jit_timer_print (gcc_jit_timer@w{ }*timer, FILE@w{ }*f_out) 8609 8610Print timing information to the given stream about activity since 8611the timer was started. 8612 8613This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test 8614for its presence using 8615 8616@example 8617#ifdef LIBGCCJIT_HAVE_TIMING_API 8618@end example 8619@end deffn 8620 8621@c Copyright (C) 2020-2021 Free Software Foundation, Inc. 8622@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 8623@c 8624@c This is free software: you can redistribute it and/or modify it 8625@c under the terms of the GNU General Public License as published by 8626@c the Free Software Foundation, either version 3 of the License, or 8627@c (at your option) any later version. 8628@c 8629@c This program is distributed in the hope that it will be useful, but 8630@c WITHOUT ANY WARRANTY; without even the implied warranty of 8631@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8632@c General Public License for more details. 8633@c 8634@c You should have received a copy of the GNU General Public License 8635@c along with this program. If not, see 8636@c <http://www.gnu.org/licenses/>. 8637 8638@node Using Assembly Language with libgccjit,,Performance,Topic Reference 8639@anchor{topics/asm doc}@anchor{131}@anchor{topics/asm using-assembly-language-with-libgccjit}@anchor{132} 8640@section Using Assembly Language with libgccjit 8641 8642 8643libgccjit has some support for directly embedding assembler instructions. 8644This is based on GCC’s support for inline @code{asm} in C code, and the 8645following assumes a familiarity with that functionality. See 8646How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html} 8647in GCC’s documentation, the “Extended Asm” section in particular. 8648 8649These entrypoints were added in @ref{122,,LIBGCCJIT_ABI_15}; you can test 8650for their presence using 8651 8652@quotation 8653 8654@example 8655#ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS 8656@end example 8657@end quotation 8658 8659@menu 8660* Adding assembler instructions within a function:: 8661* Adding top-level assembler statements:: 8662 8663@end menu 8664 8665@node Adding assembler instructions within a function,Adding top-level assembler statements,,Using Assembly Language with libgccjit 8666@anchor{topics/asm adding-assembler-instructions-within-a-function}@anchor{133} 8667@subsection Adding assembler instructions within a function 8668 8669 8670@geindex gcc_jit_extended_asm (C type) 8671@anchor{topics/asm c gcc_jit_extended_asm}@anchor{f1} 8672@deffn {C Type} gcc_jit_extended_asm 8673 8674A @cite{gcc_jit_extended_asm} represents an extended @code{asm} statement: a 8675series of low-level instructions inside a function that convert inputs 8676to outputs. 8677 8678To avoid having an API entrypoint with a very large number of 8679parameters, an extended @code{asm} statement is made in stages: 8680an initial call to create the @ref{f1,,gcc_jit_extended_asm}, 8681followed by calls to add operands and set other properties of the 8682statement. 8683 8684There are two API entrypoints for creating a @ref{f1,,gcc_jit_extended_asm}: 8685 8686 8687@itemize * 8688 8689@item 8690@ref{123,,gcc_jit_block_add_extended_asm()} for an @code{asm} statement with 8691no control flow, and 8692 8693@item 8694@ref{124,,gcc_jit_block_end_with_extended_asm_goto()} for an @code{asm goto}. 8695@end itemize 8696 8697For example, to create the equivalent of: 8698 8699@example 8700 asm ("mov %1, %0\n\t" 8701 "add $1, %0" 8702 : "=r" (dst) 8703 : "r" (src)); 8704@end example 8705 8706the following API calls could be used: 8707 8708@example 8709 gcc_jit_extended_asm *ext_asm 8710 = gcc_jit_block_add_extended_asm (block, NULL, 8711 "mov %1, %0\n\t" 8712 "add $1, %0"); 8713 gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst); 8714 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 8715 gcc_jit_lvalue_as_rvalue (src)); 8716@end example 8717 8718@cartouche 8719@quotation Warning 8720When considering the numbering of operands within an 8721extended @code{asm} statement (e.g. the @code{%0} and @code{%1} 8722above), the equivalent to the C syntax is followed i.e. all 8723output operands, then all input operands, regardless of 8724what order the calls to 8725@ref{128,,gcc_jit_extended_asm_add_output_operand()} and 8726@ref{129,,gcc_jit_extended_asm_add_input_operand()} were made in. 8727@end quotation 8728@end cartouche 8729 8730As in the C syntax, operands can be given symbolic names to avoid having 8731to number them. For example, to create the equivalent of: 8732 8733@example 8734 asm ("bsfl %[aMask], %[aIndex]" 8735 : [aIndex] "=r" (Index) 8736 : [aMask] "r" (Mask) 8737 : "cc"); 8738@end example 8739 8740the following API calls could be used: 8741 8742@example 8743 gcc_jit_extended_asm *ext_asm 8744 = gcc_jit_block_add_extended_asm (block, NULL, 8745 "bsfl %[aMask], %[aIndex]"); 8746 gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index); 8747 gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r", 8748 gcc_jit_param_as_rvalue (mask)); 8749 gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 8750@end example 8751@end deffn 8752 8753@geindex gcc_jit_block_add_extended_asm (C function) 8754@anchor{topics/asm c gcc_jit_block_add_extended_asm}@anchor{123} 8755@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) 8756 8757Create a @ref{f1,,gcc_jit_extended_asm} for an extended @code{asm} statement 8758with no control flow (i.e. without the @code{goto} qualifier). 8759 8760The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate} 8761within C’s extended @code{asm} syntax. It must be non-NULL. The call takes 8762a copy of the underlying string, so it is valid to pass in a pointer to 8763an on-stack buffer. 8764@end deffn 8765 8766@geindex gcc_jit_block_end_with_extended_asm_goto (C function) 8767@anchor{topics/asm c gcc_jit_block_end_with_extended_asm_goto}@anchor{124} 8768@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) 8769 8770Create a @ref{f1,,gcc_jit_extended_asm} for an extended @code{asm} statement 8771that may perform jumps, and use it to terminate the given block. 8772This is equivalent to the @code{goto} qualifier in C’s extended @code{asm} 8773syntax. 8774 8775For example, to create the equivalent of: 8776 8777@example 8778 asm goto ("btl %1, %0\n\t" 8779 "jc %l[carry]" 8780 : // No outputs 8781 : "r" (p1), "r" (p2) 8782 : "cc" 8783 : carry); 8784@end example 8785 8786the following API calls could be used: 8787 8788@example 8789 const char *asm_template = 8790 (use_name 8791 ? /* Label referred to by name: "%l[carry]". */ 8792 ("btl %1, %0\n\t" 8793 "jc %l[carry]") 8794 : /* Label referred to numerically: "%l2". */ 8795 ("btl %1, %0\n\t" 8796 "jc %l2")); 8797 8798 gcc_jit_extended_asm *ext_asm 8799 = gcc_jit_block_end_with_extended_asm_goto (b_start, NULL, 8800 asm_template, 8801 1, &b_carry, 8802 b_fallthru); 8803 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 8804 gcc_jit_param_as_rvalue (p1)); 8805 gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 8806 gcc_jit_param_as_rvalue (p2)); 8807 gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 8808@end example 8809 8810here referencing a @ref{28,,gcc_jit_block} named “carry”. 8811 8812@code{num_goto_blocks} must be >= 0. 8813 8814@code{goto_blocks} must be non-NULL. This corresponds to the @code{GotoLabels} 8815parameter within C’s extended @code{asm} syntax. The block names can be 8816referenced within the assembler template. 8817 8818@code{fallthrough_block} can be NULL. If non-NULL, it specifies the block 8819to fall through to after the statement. 8820 8821@cartouche 8822@quotation Note 8823This is needed since each @ref{28,,gcc_jit_block} must have a 8824single exit point, as a basic block: you can’t jump from the 8825middle of a block. A “goto” is implicitly added after the 8826asm to handle the fallthrough case, which is equivalent to what 8827would have happened in the C case. 8828@end quotation 8829@end cartouche 8830@end deffn 8831 8832@geindex gcc_jit_extended_asm_set_volatile_flag (C function) 8833@anchor{topics/asm c gcc_jit_extended_asm_set_volatile_flag}@anchor{126} 8834@deffn {C Function} void gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag) 8835 8836Set whether the @ref{f1,,gcc_jit_extended_asm} has side-effects, equivalent to the 8837volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile} 8838qualifier in C’s extended asm syntax. 8839 8840For example, to create the equivalent of: 8841 8842@example 8843asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX. 8844 "shl $32, %%rdx\n\t" // Shift the upper bits left. 8845 "or %%rdx, %0" // 'Or' in the lower bits. 8846 : "=a" (msr) 8847 : 8848 : "rdx"); 8849@end example 8850 8851the following API calls could be used: 8852 8853@example 8854 gcc_jit_extended_asm *ext_asm 8855 = gcc_jit_block_add_extended_asm 8856 (block, NULL, 8857 "rdtsc\n\t" /* Returns the time in EDX:EAX. */ 8858 "shl $32, %%rdx\n\t" /* Shift the upper bits left. */ 8859 "or %%rdx, %0"); /* 'Or' in the lower bits. */ 8860 gcc_jit_extended_asm_set_volatile_flag (ext_asm, 1); 8861 gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=a", msr); 8862 gcc_jit_extended_asm_add_clobber (ext_asm, "rdx"); 8863@end example 8864 8865where the @ref{f1,,gcc_jit_extended_asm} is flagged as volatile. 8866@end deffn 8867 8868@geindex gcc_jit_extended_asm_set_inline_flag (C function) 8869@anchor{topics/asm c gcc_jit_extended_asm_set_inline_flag}@anchor{127} 8870@deffn {C Function} void gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag) 8871 8872Set the equivalent of the 8873inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm} 8874qualifier in C’s extended @code{asm} syntax. 8875@end deffn 8876 8877@geindex gcc_jit_extended_asm_add_output_operand (C function) 8878@anchor{topics/asm c gcc_jit_extended_asm_add_output_operand}@anchor{128} 8879@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) 8880 8881Add an output operand to the extended @code{asm} statement. See the 8882Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands} 8883section of the documentation of the C syntax. 8884 8885@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of C’s 8886extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the 8887symbolic name for the operand. 8888 8889@code{constraint} corresponds to the @code{constraint} component of C’s extended 8890@code{asm} syntax. It must be non-NULL. 8891 8892@code{dest} corresponds to the @code{cvariablename} component of C’s extended 8893@code{asm} syntax. It must be non-NULL. 8894 8895@example 8896// Example with a NULL symbolic name, the equivalent of: 8897// : "=r" (dst) 8898gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst); 8899 8900// Example with a symbolic name ("aIndex"), the equivalent of: 8901// : [aIndex] "=r" (index) 8902gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index); 8903@end example 8904 8905This function can’t be called on an @code{asm goto} as such instructions can’t 8906have outputs; see the 8907Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels} 8908section of GCC’s “Extended Asm” documentation. 8909@end deffn 8910 8911@geindex gcc_jit_extended_asm_add_input_operand (C function) 8912@anchor{topics/asm c gcc_jit_extended_asm_add_input_operand}@anchor{129} 8913@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) 8914 8915Add an input operand to the extended @code{asm} statement. See the 8916Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands} 8917section of the documentation of the C syntax. 8918 8919@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of C’s 8920extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the 8921symbolic name for the operand. 8922 8923@code{constraint} corresponds to the @code{constraint} component of C’s extended 8924@code{asm} syntax. It must be non-NULL. 8925 8926@code{src} corresponds to the @code{cexpression} component of C’s extended 8927@code{asm} syntax. It must be non-NULL. 8928 8929@example 8930// Example with a NULL symbolic name, the equivalent of: 8931// : "r" (src) 8932gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", 8933 gcc_jit_lvalue_as_rvalue (src)); 8934 8935// Example with a symbolic name ("aMask"), the equivalent of: 8936// : [aMask] "r" (Mask) 8937gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r", 8938 gcc_jit_lvalue_as_rvalue (mask)); 8939@end example 8940@end deffn 8941 8942@geindex gcc_jit_extended_asm_add_clobber (C function) 8943@anchor{topics/asm c gcc_jit_extended_asm_add_clobber}@anchor{12a} 8944@deffn {C Function} void gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*victim) 8945 8946Add @cite{victim} to the list of registers clobbered by the extended @code{asm} 8947statement. It must be non-NULL. See the 8948Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#} 8949section of the documentation of the C syntax. 8950 8951Statements with multiple clobbers will require multiple calls, one per 8952clobber. 8953 8954For example: 8955 8956@example 8957gcc_jit_extended_asm_add_clobber (ext_asm, "r0"); 8958gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); 8959gcc_jit_extended_asm_add_clobber (ext_asm, "memory"); 8960@end example 8961@end deffn 8962 8963A @ref{f1,,gcc_jit_extended_asm} is a @ref{e,,gcc_jit_object} “owned” by 8964the block’s context. The following upcast is available: 8965 8966@geindex gcc_jit_extended_asm_as_object (C function) 8967@anchor{topics/asm c gcc_jit_extended_asm_as_object}@anchor{125} 8968@deffn {C Function} gcc_jit_object * gcc_jit_extended_asm_as_object (gcc_jit_extended_asm@w{ }*ext_asm) 8969 8970Upcast from extended @code{asm} to object. 8971@end deffn 8972 8973@node Adding top-level assembler statements,,Adding assembler instructions within a function,Using Assembly Language with libgccjit 8974@anchor{topics/asm adding-top-level-assembler-statements}@anchor{134} 8975@subsection Adding top-level assembler statements 8976 8977 8978In addition to creating extended @code{asm} instructions within a function, 8979there is support for creating “top-level” assembler statements, outside 8980of any function. 8981 8982@geindex gcc_jit_context_add_top_level_asm (C function) 8983@anchor{topics/asm c gcc_jit_context_add_top_level_asm}@anchor{12b} 8984@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) 8985 8986Create a set of top-level asm statements, analogous to those created 8987by GCC’s “basic” @code{asm} syntax in C at file scope. 8988 8989For example, to create the equivalent of: 8990 8991@example 8992 asm ("\t.pushsection .text\n" 8993 "\t.globl add_asm\n" 8994 "\t.type add_asm, @@function\n" 8995 "add_asm:\n" 8996 "\tmovq %rdi, %rax\n" 8997 "\tadd %rsi, %rax\n" 8998 "\tret\n" 8999 "\t.popsection\n"); 9000@end example 9001 9002the following API calls could be used: 9003 9004@example 9005 gcc_jit_context_add_top_level_asm (ctxt, NULL, 9006 "\t.pushsection .text\n" 9007 "\t.globl add_asm\n" 9008 "\t.type add_asm, @@function\n" 9009 "add_asm:\n" 9010 "\tmovq %rdi, %rax\n" 9011 "\tadd %rsi, %rax\n" 9012 "\tret\n" 9013 "\t# some asm here\n" 9014 "\t.popsection\n"); 9015@end example 9016@end deffn 9017 9018@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 9019@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 9020@c 9021@c This is free software: you can redistribute it and/or modify it 9022@c under the terms of the GNU General Public License as published by 9023@c the Free Software Foundation, either version 3 of the License, or 9024@c (at your option) any later version. 9025@c 9026@c This program is distributed in the hope that it will be useful, but 9027@c WITHOUT ANY WARRANTY; without even the implied warranty of 9028@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9029@c General Public License for more details. 9030@c 9031@c You should have received a copy of the GNU General Public License 9032@c along with this program. If not, see 9033@c <http://www.gnu.org/licenses/>. 9034 9035@node C++ bindings for libgccjit,Internals,Topic Reference,Top 9036@anchor{cp/index doc}@anchor{135}@anchor{cp/index c-bindings-for-libgccjit}@anchor{136} 9037@chapter C++ bindings for libgccjit 9038 9039 9040This document describes the C++ bindings to 9041libgccjit@footnote{http://gcc.gnu.org/wiki/JIT}, an API for embedding GCC 9042inside programs and libraries. 9043 9044The C++ bindings consist of a single header file @code{libgccjit++.h}. 9045 9046This is a collection of “thin” wrapper classes around the C API. 9047Everything is an inline function, implemented in terms of the C API, 9048so there is nothing extra to link against. 9049 9050Contents: 9051 9052@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 9053@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 9054@c 9055@c This is free software: you can redistribute it and/or modify it 9056@c under the terms of the GNU General Public License as published by 9057@c the Free Software Foundation, either version 3 of the License, or 9058@c (at your option) any later version. 9059@c 9060@c This program is distributed in the hope that it will be useful, but 9061@c WITHOUT ANY WARRANTY; without even the implied warranty of 9062@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9063@c General Public License for more details. 9064@c 9065@c You should have received a copy of the GNU General Public License 9066@c along with this program. If not, see 9067@c <http://www.gnu.org/licenses/>. 9068 9069@menu 9070* Tutorial: Tutorial<2>. 9071* Topic Reference: Topic Reference<2>. 9072 9073@end menu 9074 9075@node Tutorial<2>,Topic Reference<2>,,C++ bindings for libgccjit 9076@anchor{cp/intro/index doc}@anchor{137}@anchor{cp/intro/index tutorial}@anchor{138} 9077@section Tutorial 9078 9079 9080@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 9081@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 9082@c 9083@c This is free software: you can redistribute it and/or modify it 9084@c under the terms of the GNU General Public License as published by 9085@c the Free Software Foundation, either version 3 of the License, or 9086@c (at your option) any later version. 9087@c 9088@c This program is distributed in the hope that it will be useful, but 9089@c WITHOUT ANY WARRANTY; without even the implied warranty of 9090@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9091@c General Public License for more details. 9092@c 9093@c You should have received a copy of the GNU General Public License 9094@c along with this program. If not, see 9095@c <http://www.gnu.org/licenses/>. 9096 9097@menu 9098* Tutorial part 1; “Hello world”: Tutorial part 1 “Hello world”<2>. 9099* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>. 9100* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>. 9101* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>. 9102 9103@end menu 9104 9105@node Tutorial part 1 “Hello world”<2>,Tutorial part 2 Creating a trivial machine code function<2>,,Tutorial<2> 9106@anchor{cp/intro/tutorial01 doc}@anchor{139}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{13a} 9107@subsection Tutorial part 1: “Hello world” 9108 9109 9110Before we look at the details of the API, let’s look at building and 9111running programs that use the library. 9112 9113Here’s a toy “hello world” program that uses the library’s C++ API to 9114synthesize a call to @cite{printf} and uses it to write a message to stdout. 9115 9116Don’t worry about the content of the program for now; we’ll cover 9117the details in later parts of this tutorial. 9118 9119@quotation 9120 9121@example 9122/* Smoketest example for libgccjit.so C++ API 9123 Copyright (C) 2014-2021 Free Software Foundation, Inc. 9124 9125This file is part of GCC. 9126 9127GCC is free software; you can redistribute it and/or modify it 9128under the terms of the GNU General Public License as published by 9129the Free Software Foundation; either version 3, or (at your option) 9130any later version. 9131 9132GCC is distributed in the hope that it will be useful, but 9133WITHOUT ANY WARRANTY; without even the implied warranty of 9134MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9135General Public License for more details. 9136 9137You should have received a copy of the GNU General Public License 9138along with GCC; see the file COPYING3. If not see 9139<http://www.gnu.org/licenses/>. */ 9140 9141#include <libgccjit++.h> 9142 9143#include <stdlib.h> 9144#include <stdio.h> 9145 9146static void 9147create_code (gccjit::context ctxt) 9148@{ 9149 /* Let's try to inject the equivalent of this C code: 9150 void 9151 greet (const char *name) 9152 @{ 9153 printf ("hello %s\n", name); 9154 @} 9155 */ 9156 gccjit::type void_type = ctxt.get_type (GCC_JIT_TYPE_VOID); 9157 gccjit::type const_char_ptr_type = 9158 ctxt.get_type (GCC_JIT_TYPE_CONST_CHAR_PTR); 9159 gccjit::param param_name = 9160 ctxt.new_param (const_char_ptr_type, "name"); 9161 std::vector<gccjit::param> func_params; 9162 func_params.push_back (param_name); 9163 gccjit::function func = 9164 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 9165 void_type, 9166 "greet", 9167 func_params, 0); 9168 9169 gccjit::param param_format = 9170 ctxt.new_param (const_char_ptr_type, "format"); 9171 std::vector<gccjit::param> printf_params; 9172 printf_params.push_back (param_format); 9173 gccjit::function printf_func = 9174 ctxt.new_function (GCC_JIT_FUNCTION_IMPORTED, 9175 ctxt.get_type (GCC_JIT_TYPE_INT), 9176 "printf", 9177 printf_params, 1); 9178 9179 gccjit::block block = func.new_block (); 9180 block.add_eval (ctxt.new_call (printf_func, 9181 ctxt.new_rvalue ("hello %s\n"), 9182 param_name)); 9183 block.end_with_return (); 9184@} 9185 9186int 9187main (int argc, char **argv) 9188@{ 9189 gccjit::context ctxt; 9190 gcc_jit_result *result; 9191 9192 /* Get a "context" object for working with the library. */ 9193 ctxt = gccjit::context::acquire (); 9194 9195 /* Set some options on the context. 9196 Turn this on to see the code being generated, in assembler form. */ 9197 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 0); 9198 9199 /* Populate the context. */ 9200 create_code (ctxt); 9201 9202 /* Compile the code. */ 9203 result = ctxt.compile (); 9204 if (!result) 9205 @{ 9206 fprintf (stderr, "NULL result"); 9207 exit (1); 9208 @} 9209 9210 ctxt.release (); 9211 9212 /* Extract the generated code from "result". */ 9213 typedef void (*fn_type) (const char *); 9214 fn_type greet = 9215 (fn_type)gcc_jit_result_get_code (result, "greet"); 9216 if (!greet) 9217 @{ 9218 fprintf (stderr, "NULL greet"); 9219 exit (1); 9220 @} 9221 9222 /* Now call the generated function: */ 9223 greet ("world"); 9224 fflush (stdout); 9225 9226 gcc_jit_result_release (result); 9227 return 0; 9228@} 9229@end example 9230@end quotation 9231 9232Copy the above to @cite{tut01-hello-world.cc}. 9233 9234Assuming you have the jit library installed, build the test program 9235using: 9236 9237@example 9238$ gcc \ 9239 tut01-hello-world.cc \ 9240 -o tut01-hello-world \ 9241 -lgccjit 9242@end example 9243 9244You should then be able to run the built program: 9245 9246@example 9247$ ./tut01-hello-world 9248hello world 9249@end example 9250 9251@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 9252@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 9253@c 9254@c This is free software: you can redistribute it and/or modify it 9255@c under the terms of the GNU General Public License as published by 9256@c the Free Software Foundation, either version 3 of the License, or 9257@c (at your option) any later version. 9258@c 9259@c This program is distributed in the hope that it will be useful, but 9260@c WITHOUT ANY WARRANTY; without even the implied warranty of 9261@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9262@c General Public License for more details. 9263@c 9264@c You should have received a copy of the GNU General Public License 9265@c along with this program. If not, see 9266@c <http://www.gnu.org/licenses/>. 9267 9268@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> 9269@anchor{cp/intro/tutorial02 doc}@anchor{13b}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{13c} 9270@subsection Tutorial part 2: Creating a trivial machine code function 9271 9272 9273Consider this C function: 9274 9275@example 9276int square (int i) 9277@{ 9278 return i * i; 9279@} 9280@end example 9281 9282How can we construct this at run-time using libgccjit’s C++ API? 9283 9284First we need to include the relevant header: 9285 9286@example 9287#include <libgccjit++.h> 9288@end example 9289 9290All state associated with compilation is associated with a 9291@ref{13d,,gccjit;;context}, which is a thin C++ wrapper around the C API’s 9292@ref{8,,gcc_jit_context *}. 9293 9294Create one using @ref{13e,,gccjit;;context;;acquire()}: 9295 9296@example 9297gccjit::context ctxt; 9298ctxt = gccjit::context::acquire (); 9299@end example 9300 9301The JIT library has a system of types. It is statically-typed: every 9302expression is of a specific type, fixed at compile-time. In our example, 9303all of the expressions are of the C @cite{int} type, so let’s obtain this from 9304the context, as a @ref{13f,,gccjit;;type}, using 9305@ref{140,,gccjit;;context;;get_type()}: 9306 9307@example 9308gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 9309@end example 9310 9311@ref{13f,,gccjit;;type} is an example of a “contextual” object: every 9312entity in the API is associated with a @ref{13d,,gccjit;;context}. 9313 9314Memory management is easy: all such “contextual” objects are automatically 9315cleaned up for you when the context is released, using 9316@ref{141,,gccjit;;context;;release()}: 9317 9318@example 9319ctxt.release (); 9320@end example 9321 9322so you don’t need to manually track and cleanup all objects, just the 9323contexts. 9324 9325All of the C++ classes in the API are thin wrappers around pointers to 9326types in the C API. 9327 9328The C++ class hierarchy within the @code{gccjit} namespace looks like this: 9329 9330@example 9331+- object 9332 +- location 9333 +- type 9334 +- struct 9335 +- field 9336 +- function 9337 +- block 9338 +- rvalue 9339 +- lvalue 9340 +- param 9341@end example 9342 9343One thing you can do with a @ref{142,,gccjit;;object} is 9344to ask it for a human-readable description as a @code{std::string}, using 9345@ref{143,,gccjit;;object;;get_debug_string()}: 9346 9347@example 9348printf ("obj: %s\n", obj.get_debug_string ().c_str ()); 9349@end example 9350 9351giving this text on stdout: 9352 9353@example 9354obj: int 9355@end example 9356 9357This is invaluable when debugging. 9358 9359Let’s create the function. To do so, we first need to construct 9360its single parameter, specifying its type and giving it a name, 9361using @ref{144,,gccjit;;context;;new_param()}: 9362 9363@example 9364gccjit::param param_i = ctxt.new_param (int_type, "i"); 9365@end example 9366 9367and we can then make a vector of all of the params of the function, 9368in this case just one: 9369 9370@example 9371std::vector<gccjit::param> params; 9372params.push_back (param_i); 9373@end example 9374 9375Now we can create the function, using 9376@code{gccjit::context::new_function()}: 9377 9378@example 9379gccjit::function func = 9380 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 9381 int_type, 9382 "square", 9383 params, 9384 0); 9385@end example 9386 9387To define the code within the function, we must create basic blocks 9388containing statements. 9389 9390Every basic block contains a list of statements, eventually terminated 9391by a statement that either returns, or jumps to another basic block. 9392 9393Our function has no control-flow, so we just need one basic block: 9394 9395@example 9396gccjit::block block = func.new_block (); 9397@end example 9398 9399Our basic block is relatively simple: it immediately terminates by 9400returning the value of an expression. 9401 9402We can build the expression using @ref{145,,gccjit;;context;;new_binary_op()}: 9403 9404@example 9405gccjit::rvalue expr = 9406 ctxt.new_binary_op ( 9407 GCC_JIT_BINARY_OP_MULT, int_type, 9408 param_i, param_i); 9409@end example 9410 9411A @ref{146,,gccjit;;rvalue} is another example of a 9412@ref{142,,gccjit;;object} subclass. As before, we can print it with 9413@ref{143,,gccjit;;object;;get_debug_string()}. 9414 9415@example 9416printf ("expr: %s\n", expr.get_debug_string ().c_str ()); 9417@end example 9418 9419giving this output: 9420 9421@example 9422expr: i * i 9423@end example 9424 9425Note that @ref{146,,gccjit;;rvalue} provides numerous overloaded operators 9426which can be used to dramatically reduce the amount of typing needed. 9427We can build the above binary operation more directly with this one-liner: 9428 9429@example 9430gccjit::rvalue expr = param_i * param_i; 9431@end example 9432 9433Creating the expression in itself doesn’t do anything; we have to add 9434this expression to a statement within the block. In this case, we use it 9435to build a return statement, which terminates the basic block: 9436 9437@example 9438block.end_with_return (expr); 9439@end example 9440 9441OK, we’ve populated the context. We can now compile it using 9442@ref{147,,gccjit;;context;;compile()}: 9443 9444@example 9445gcc_jit_result *result; 9446result = ctxt.compile (); 9447@end example 9448 9449and get a @ref{16,,gcc_jit_result *}. 9450 9451We can now use @ref{17,,gcc_jit_result_get_code()} to look up a specific 9452machine code routine within the result, in this case, the function we 9453created above. 9454 9455@example 9456void *fn_ptr = gcc_jit_result_get_code (result, "square"); 9457if (!fn_ptr) 9458 @{ 9459 fprintf (stderr, "NULL fn_ptr"); 9460 goto error; 9461 @} 9462@end example 9463 9464We can now cast the pointer to an appropriate function pointer type, and 9465then call it: 9466 9467@example 9468typedef int (*fn_type) (int); 9469fn_type square = (fn_type)fn_ptr; 9470printf ("result: %d", square (5)); 9471@end example 9472 9473@example 9474result: 25 9475@end example 9476 9477@menu 9478* Options: Options<3>. 9479* Full example: Full example<3>. 9480 9481@end menu 9482 9483@node Options<3>,Full example<3>,,Tutorial part 2 Creating a trivial machine code function<2> 9484@anchor{cp/intro/tutorial02 options}@anchor{148} 9485@subsubsection Options 9486 9487 9488To get more information on what’s going on, you can set debugging flags 9489on the context using @ref{149,,gccjit;;context;;set_bool_option()}. 9490 9491@c (I'm deliberately not mentioning 9492@c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think 9493@c it's probably more of use to implementors than to users) 9494 9495Setting @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE} will dump a 9496C-like representation to stderr when you compile (GCC’s “GIMPLE” 9497representation): 9498 9499@example 9500ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); 9501result = ctxt.compile (); 9502@end example 9503 9504@example 9505square (signed int i) 9506@{ 9507 signed int D.260; 9508 9509 entry: 9510 D.260 = i * i; 9511 return D.260; 9512@} 9513@end example 9514 9515We can see the generated machine code in assembler form (on stderr) by 9516setting @ref{1d,,GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE} on the context 9517before compiling: 9518 9519@example 9520ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1); 9521result = ctxt.compile (); 9522@end example 9523 9524@example 9525 .file "fake.c" 9526 .text 9527 .globl square 9528 .type square, @@function 9529square: 9530.LFB6: 9531 .cfi_startproc 9532 pushq %rbp 9533 .cfi_def_cfa_offset 16 9534 .cfi_offset 6, -16 9535 movq %rsp, %rbp 9536 .cfi_def_cfa_register 6 9537 movl %edi, -4(%rbp) 9538.L14: 9539 movl -4(%rbp), %eax 9540 imull -4(%rbp), %eax 9541 popq %rbp 9542 .cfi_def_cfa 7, 8 9543 ret 9544 .cfi_endproc 9545.LFE6: 9546 .size square, .-square 9547 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 9548 .section .note.GNU-stack,"",@@progbits 9549@end example 9550 9551By default, no optimizations are performed, the equivalent of GCC’s 9552@cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling 9553@ref{14a,,gccjit;;context;;set_int_option()} with 9554@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 9555 9556@example 9557ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); 9558@end example 9559 9560@example 9561 .file "fake.c" 9562 .text 9563 .p2align 4,,15 9564 .globl square 9565 .type square, @@function 9566square: 9567.LFB7: 9568 .cfi_startproc 9569.L16: 9570 movl %edi, %eax 9571 imull %edi, %eax 9572 ret 9573 .cfi_endproc 9574.LFE7: 9575 .size square, .-square 9576 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)" 9577 .section .note.GNU-stack,"",@@progbits 9578@end example 9579 9580Naturally this has only a small effect on such a trivial function. 9581 9582@node Full example<3>,,Options<3>,Tutorial part 2 Creating a trivial machine code function<2> 9583@anchor{cp/intro/tutorial02 full-example}@anchor{14b} 9584@subsubsection Full example 9585 9586 9587Here’s what the above looks like as a complete program: 9588 9589@quotation 9590 9591@example 9592/* Usage example for libgccjit.so's C++ API 9593 Copyright (C) 2014-2021 Free Software Foundation, Inc. 9594 9595This file is part of GCC. 9596 9597GCC is free software; you can redistribute it and/or modify it 9598under the terms of the GNU General Public License as published by 9599the Free Software Foundation; either version 3, or (at your option) 9600any later version. 9601 9602GCC is distributed in the hope that it will be useful, but 9603WITHOUT ANY WARRANTY; without even the implied warranty of 9604MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9605General Public License for more details. 9606 9607You should have received a copy of the GNU General Public License 9608along with GCC; see the file COPYING3. If not see 9609<http://www.gnu.org/licenses/>. */ 9610 9611#include <libgccjit++.h> 9612 9613#include <stdlib.h> 9614#include <stdio.h> 9615 9616void 9617create_code (gccjit::context ctxt) 9618@{ 9619 /* Let's try to inject the equivalent of this C code: 9620 9621 int square (int i) 9622 @{ 9623 return i * i; 9624 @} 9625 */ 9626 gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 9627 gccjit::param param_i = ctxt.new_param (int_type, "i"); 9628 std::vector<gccjit::param> params; 9629 params.push_back (param_i); 9630 gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 9631 int_type, 9632 "square", 9633 params, 0); 9634 9635 gccjit::block block = func.new_block (); 9636 9637 gccjit::rvalue expr = 9638 ctxt.new_binary_op (GCC_JIT_BINARY_OP_MULT, int_type, 9639 param_i, param_i); 9640 9641 block.end_with_return (expr); 9642@} 9643 9644int 9645main (int argc, char **argv) 9646@{ 9647 /* Get a "context" object for working with the library. */ 9648 gccjit::context ctxt = gccjit::context::acquire (); 9649 9650 /* Set some options on the context. 9651 Turn this on to see the code being generated, in assembler form. */ 9652 ctxt.set_bool_option ( 9653 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 9654 0); 9655 9656 /* Populate the context. */ 9657 create_code (ctxt); 9658 9659 /* Compile the code. */ 9660 gcc_jit_result *result = ctxt.compile (); 9661 9662 /* We're done with the context; we can release it: */ 9663 ctxt.release (); 9664 9665 if (!result) 9666 @{ 9667 fprintf (stderr, "NULL result"); 9668 return 1; 9669 @} 9670 9671 /* Extract the generated code from "result". */ 9672 void *fn_ptr = gcc_jit_result_get_code (result, "square"); 9673 if (!fn_ptr) 9674 @{ 9675 fprintf (stderr, "NULL fn_ptr"); 9676 gcc_jit_result_release (result); 9677 return 1; 9678 @} 9679 9680 typedef int (*fn_type) (int); 9681 fn_type square = (fn_type)fn_ptr; 9682 printf ("result: %d\n", square (5)); 9683 9684 gcc_jit_result_release (result); 9685 return 0; 9686@} 9687@end example 9688@end quotation 9689 9690Building and running it: 9691 9692@example 9693$ gcc \ 9694 tut02-square.cc \ 9695 -o tut02-square \ 9696 -lgccjit 9697 9698# Run the built program: 9699$ ./tut02-square 9700result: 25 9701@end example 9702 9703@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 9704@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 9705@c 9706@c This is free software: you can redistribute it and/or modify it 9707@c under the terms of the GNU General Public License as published by 9708@c the Free Software Foundation, either version 3 of the License, or 9709@c (at your option) any later version. 9710@c 9711@c This program is distributed in the hope that it will be useful, but 9712@c WITHOUT ANY WARRANTY; without even the implied warranty of 9713@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9714@c General Public License for more details. 9715@c 9716@c You should have received a copy of the GNU General Public License 9717@c along with this program. If not, see 9718@c <http://www.gnu.org/licenses/>. 9719 9720@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> 9721@anchor{cp/intro/tutorial03 doc}@anchor{14c}@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{14d} 9722@subsection Tutorial part 3: Loops and variables 9723 9724 9725Consider this C function: 9726 9727@quotation 9728 9729@example 9730int loop_test (int n) 9731@{ 9732 int sum = 0; 9733 for (int i = 0; i < n; i++) 9734 sum += i * i; 9735 return sum; 9736@} 9737@end example 9738@end quotation 9739 9740This example demonstrates some more features of libgccjit, with local 9741variables and a loop. 9742 9743To break this down into libgccjit terms, it’s usually easier to reword 9744the @cite{for} loop as a @cite{while} loop, giving: 9745 9746@quotation 9747 9748@example 9749int loop_test (int n) 9750@{ 9751 int sum = 0; 9752 int i = 0; 9753 while (i < n) 9754 @{ 9755 sum += i * i; 9756 i++; 9757 @} 9758 return sum; 9759@} 9760@end example 9761@end quotation 9762 9763Here’s what the final control flow graph will look like: 9764 9765@quotation 9766 9767 9768@float Figure 9769 9770@image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png} 9771 9772@end float 9773 9774@end quotation 9775 9776As before, we include the libgccjit++ header and make a 9777@ref{13d,,gccjit;;context}. 9778 9779@example 9780#include <libgccjit++.h> 9781 9782void test (void) 9783@{ 9784 gccjit::context ctxt; 9785 ctxt = gccjit::context::acquire (); 9786@end example 9787 9788The function works with the C @cite{int} type. 9789 9790In the previous tutorial we acquired this via 9791 9792@example 9793gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_INT); 9794@end example 9795 9796though we could equally well make it work on, say, @cite{double}: 9797 9798@example 9799gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_DOUBLE); 9800@end example 9801 9802For integer types we can use @code{gccjit::context::get_int_type} 9803to directly bind a specific type: 9804 9805@example 9806gccjit::type the_type = ctxt.get_int_type <int> (); 9807@end example 9808 9809Let’s build the function: 9810 9811@example 9812gcc_jit_param n = ctxt.new_param (the_type, "n"); 9813std::vector<gccjit::param> params; 9814params.push_back (n); 9815gccjit::function func = 9816 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 9817 return_type, 9818 "loop_test", 9819 params, 0); 9820@end example 9821 9822@menu 9823* Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>. 9824* Control flow: Control flow<2>. 9825* Visualizing the control flow graph: Visualizing the control flow graph<2>. 9826* Full example: Full example<4>. 9827 9828@end menu 9829 9830@node Expressions lvalues and rvalues<2>,Control flow<2>,,Tutorial part 3 Loops and variables<2> 9831@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{14e} 9832@subsubsection Expressions: lvalues and rvalues 9833 9834 9835The base class of expression is the @ref{146,,gccjit;;rvalue}, 9836representing an expression that can be on the @emph{right}-hand side of 9837an assignment: a value that can be computed somehow, and assigned 9838@emph{to} a storage area (such as a variable). It has a specific 9839@ref{13f,,gccjit;;type}. 9840 9841Anothe important class is @ref{14f,,gccjit;;lvalue}. 9842A @ref{14f,,gccjit;;lvalue}. is something that can of the @emph{left}-hand 9843side of an assignment: a storage area (such as a variable). 9844 9845In other words, every assignment can be thought of as: 9846 9847@example 9848LVALUE = RVALUE; 9849@end example 9850 9851Note that @ref{14f,,gccjit;;lvalue} is a subclass of 9852@ref{146,,gccjit;;rvalue}, where in an assignment of the form: 9853 9854@example 9855LVALUE_A = LVALUE_B; 9856@end example 9857 9858the @cite{LVALUE_B} implies reading the current value of that storage 9859area, assigning it into the @cite{LVALUE_A}. 9860 9861So far the only expressions we’ve seen are from the previous tutorial: 9862 9863 9864@enumerate 9865 9866@item 9867the multiplication @cite{i * i}: 9868@end enumerate 9869 9870@quotation 9871 9872@example 9873gccjit::rvalue expr = 9874 ctxt.new_binary_op ( 9875 GCC_JIT_BINARY_OP_MULT, int_type, 9876 param_i, param_i); 9877 9878/* Alternatively, using operator-overloading: */ 9879gccjit::rvalue expr = param_i * param_i; 9880@end example 9881 9882which is a @ref{146,,gccjit;;rvalue}, and 9883@end quotation 9884 9885 9886@enumerate 2 9887 9888@item 9889the various function parameters: @cite{param_i} and @cite{param_n}, instances of 9890@ref{150,,gccjit;;param}, which is a subclass of @ref{14f,,gccjit;;lvalue} 9891(and, in turn, of @ref{146,,gccjit;;rvalue}): 9892we can both read from and write to function parameters within the 9893body of a function. 9894@end enumerate 9895 9896Our new example has a new kind of expression: we have two local 9897variables. We create them by calling 9898@ref{151,,gccjit;;function;;new_local()}, supplying a type and a name: 9899 9900@example 9901/* Build locals: */ 9902gccjit::lvalue i = func.new_local (the_type, "i"); 9903gccjit::lvalue sum = func.new_local (the_type, "sum"); 9904@end example 9905 9906These are instances of @ref{14f,,gccjit;;lvalue} - they can be read from 9907and written to. 9908 9909Note that there is no precanned way to create @emph{and} initialize a variable 9910like in C: 9911 9912@example 9913int i = 0; 9914@end example 9915 9916Instead, having added the local to the function, we have to separately add 9917an assignment of @cite{0} to @cite{local_i} at the beginning of the function. 9918 9919@node Control flow<2>,Visualizing the control flow graph<2>,Expressions lvalues and rvalues<2>,Tutorial part 3 Loops and variables<2> 9920@anchor{cp/intro/tutorial03 control-flow}@anchor{152} 9921@subsubsection Control flow 9922 9923 9924This function has a loop, so we need to build some basic blocks to 9925handle the control flow. In this case, we need 4 blocks: 9926 9927 9928@enumerate 9929 9930@item 9931before the loop (initializing the locals) 9932 9933@item 9934the conditional at the top of the loop (comparing @cite{i < n}) 9935 9936@item 9937the body of the loop 9938 9939@item 9940after the loop terminates (@cite{return sum}) 9941@end enumerate 9942 9943so we create these as @ref{153,,gccjit;;block} instances within the 9944@ref{154,,gccjit;;function}: 9945 9946@example 9947gccjit::block b_initial = func.new_block ("initial"); 9948gccjit::block b_loop_cond = func.new_block ("loop_cond"); 9949gccjit::block b_loop_body = func.new_block ("loop_body"); 9950gccjit::block b_after_loop = func.new_block ("after_loop"); 9951@end example 9952 9953We now populate each block with statements. 9954 9955The entry block @cite{b_initial} consists of initializations followed by a jump 9956to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using 9957@ref{155,,gccjit;;block;;add_assignment()} to add 9958an assignment statement, and using @ref{156,,gccjit;;context;;zero()} to get 9959the constant value @cite{0} for the relevant type for the right-hand side of 9960the assignment: 9961 9962@example 9963/* sum = 0; */ 9964b_initial.add_assignment (sum, ctxt.zero (the_type)); 9965 9966/* i = 0; */ 9967b_initial.add_assignment (i, ctxt.zero (the_type)); 9968@end example 9969 9970We can then terminate the entry block by jumping to the conditional: 9971 9972@example 9973b_initial.end_with_jump (b_loop_cond); 9974@end example 9975 9976The conditional block is equivalent to the line @cite{while (i < n)} from our 9977C example. It contains a single statement: a conditional, which jumps to 9978one of two destination blocks depending on a boolean 9979@ref{146,,gccjit;;rvalue}, in this case the comparison of @cite{i} and @cite{n}. 9980 9981We could build the comparison using @ref{157,,gccjit;;context;;new_comparison()}: 9982 9983@example 9984gccjit::rvalue guard = 9985 ctxt.new_comparison (GCC_JIT_COMPARISON_GE, 9986 i, n); 9987@end example 9988 9989and can then use this to add @cite{b_loop_cond}’s sole statement, via 9990@ref{158,,gccjit;;block;;end_with_conditional()}: 9991 9992@example 9993b_loop_cond.end_with_conditional (guard, 9994 b_after_loop, // on_true 9995 b_loop_body); // on_false 9996@end example 9997 9998However @ref{146,,gccjit;;rvalue} has overloaded operators for this, so we 9999express the conditional as 10000 10001@example 10002gccjit::rvalue guard = (i >= n); 10003@end example 10004 10005and hence we can write the block more concisely as: 10006 10007@example 10008b_loop_cond.end_with_conditional ( 10009 i >= n, 10010 b_after_loop, // on_true 10011 b_loop_body); // on_false 10012@end example 10013 10014Next, we populate the body of the loop. 10015 10016The C statement @cite{sum += i * i;} is an assignment operation, where an 10017lvalue is modified “in-place”. We use 10018@ref{159,,gccjit;;block;;add_assignment_op()} to handle these operations: 10019 10020@example 10021/* sum += i * i */ 10022b_loop_body.add_assignment_op (sum, 10023 GCC_JIT_BINARY_OP_PLUS, 10024 i * i); 10025@end example 10026 10027The @cite{i++} can be thought of as @cite{i += 1}, and can thus be handled in 10028a similar way. We use @ref{2f,,gcc_jit_context_one()} to get the constant 10029value @cite{1} (for the relevant type) for the right-hand side 10030of the assignment. 10031 10032@example 10033/* i++ */ 10034b_loop_body.add_assignment_op (i, 10035 GCC_JIT_BINARY_OP_PLUS, 10036 ctxt.one (the_type)); 10037@end example 10038 10039@cartouche 10040@quotation Note 10041For numeric constants other than 0 or 1, we could use 10042@ref{15a,,gccjit;;context;;new_rvalue()}, which has overloads 10043for both @code{int} and @code{double}. 10044@end quotation 10045@end cartouche 10046 10047The loop body completes by jumping back to the conditional: 10048 10049@example 10050b_loop_body.end_with_jump (b_loop_cond); 10051@end example 10052 10053Finally, we populate the @cite{b_after_loop} block, reached when the loop 10054conditional is false. We want to generate the equivalent of: 10055 10056@example 10057return sum; 10058@end example 10059 10060so the block is just one statement: 10061 10062@example 10063/* return sum */ 10064b_after_loop.end_with_return (sum); 10065@end example 10066 10067@cartouche 10068@quotation Note 10069You can intermingle block creation with statement creation, 10070but given that the terminator statements generally include references 10071to other blocks, I find it’s clearer to create all the blocks, 10072@emph{then} all the statements. 10073@end quotation 10074@end cartouche 10075 10076We’ve finished populating the function. As before, we can now compile it 10077to machine code: 10078 10079@example 10080gcc_jit_result *result; 10081result = ctxt.compile (); 10082 10083ctxt.release (); 10084 10085if (!result) 10086 @{ 10087 fprintf (stderr, "NULL result"); 10088 return 1; 10089 @} 10090 10091typedef int (*loop_test_fn_type) (int); 10092loop_test_fn_type loop_test = 10093 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 10094if (!loop_test) 10095 @{ 10096 fprintf (stderr, "NULL loop_test"); 10097 gcc_jit_result_release (result); 10098 return 1; 10099 @} 10100printf ("result: %d", loop_test (10)); 10101@end example 10102 10103@example 10104result: 285 10105@end example 10106 10107@node Visualizing the control flow graph<2>,Full example<4>,Control flow<2>,Tutorial part 3 Loops and variables<2> 10108@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{15b} 10109@subsubsection Visualizing the control flow graph 10110 10111 10112You can see the control flow graph of a function using 10113@ref{15c,,gccjit;;function;;dump_to_dot()}: 10114 10115@example 10116func.dump_to_dot ("/tmp/sum-of-squares.dot"); 10117@end example 10118 10119giving a .dot file in GraphViz format. 10120 10121You can convert this to an image using @cite{dot}: 10122 10123@example 10124$ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png 10125@end example 10126 10127or use a viewer (my preferred one is xdot.py; see 10128@indicateurl{https://github.com/jrfonseca/xdot.py}; on Fedora you can 10129install it with @cite{yum install python-xdot}): 10130 10131@quotation 10132 10133 10134@float Figure 10135 10136@image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png} 10137 10138@end float 10139 10140@end quotation 10141 10142@node Full example<4>,,Visualizing the control flow graph<2>,Tutorial part 3 Loops and variables<2> 10143@anchor{cp/intro/tutorial03 full-example}@anchor{15d} 10144@subsubsection Full example 10145 10146 10147@quotation 10148 10149@example 10150/* Usage example for libgccjit.so's C++ API 10151 Copyright (C) 2014-2021 Free Software Foundation, Inc. 10152 10153This file is part of GCC. 10154 10155GCC is free software; you can redistribute it and/or modify it 10156under the terms of the GNU General Public License as published by 10157the Free Software Foundation; either version 3, or (at your option) 10158any later version. 10159 10160GCC is distributed in the hope that it will be useful, but 10161WITHOUT ANY WARRANTY; without even the implied warranty of 10162MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10163General Public License for more details. 10164 10165You should have received a copy of the GNU General Public License 10166along with GCC; see the file COPYING3. If not see 10167<http://www.gnu.org/licenses/>. */ 10168 10169#include <libgccjit++.h> 10170 10171#include <stdlib.h> 10172#include <stdio.h> 10173 10174void 10175create_code (gccjit::context ctxt) 10176@{ 10177 /* 10178 Simple sum-of-squares, to test conditionals and looping 10179 10180 int loop_test (int n) 10181 @{ 10182 int i; 10183 int sum = 0; 10184 for (i = 0; i < n ; i ++) 10185 @{ 10186 sum += i * i; 10187 @} 10188 return sum; 10189 */ 10190 gccjit::type the_type = ctxt.get_int_type <int> (); 10191 gccjit::type return_type = the_type; 10192 10193 gccjit::param n = ctxt.new_param (the_type, "n"); 10194 std::vector<gccjit::param> params; 10195 params.push_back (n); 10196 gccjit::function func = 10197 ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10198 return_type, 10199 "loop_test", 10200 params, 0); 10201 10202 /* Build locals: */ 10203 gccjit::lvalue i = func.new_local (the_type, "i"); 10204 gccjit::lvalue sum = func.new_local (the_type, "sum"); 10205 10206 gccjit::block b_initial = func.new_block ("initial"); 10207 gccjit::block b_loop_cond = func.new_block ("loop_cond"); 10208 gccjit::block b_loop_body = func.new_block ("loop_body"); 10209 gccjit::block b_after_loop = func.new_block ("after_loop"); 10210 10211 /* sum = 0; */ 10212 b_initial.add_assignment (sum, ctxt.zero (the_type)); 10213 10214 /* i = 0; */ 10215 b_initial.add_assignment (i, ctxt.zero (the_type)); 10216 10217 b_initial.end_with_jump (b_loop_cond); 10218 10219 /* if (i >= n) */ 10220 b_loop_cond.end_with_conditional ( 10221 i >= n, 10222 b_after_loop, 10223 b_loop_body); 10224 10225 /* sum += i * i */ 10226 b_loop_body.add_assignment_op (sum, 10227 GCC_JIT_BINARY_OP_PLUS, 10228 i * i); 10229 10230 /* i++ */ 10231 b_loop_body.add_assignment_op (i, 10232 GCC_JIT_BINARY_OP_PLUS, 10233 ctxt.one (the_type)); 10234 10235 b_loop_body.end_with_jump (b_loop_cond); 10236 10237 /* return sum */ 10238 b_after_loop.end_with_return (sum); 10239@} 10240 10241int 10242main (int argc, char **argv) 10243@{ 10244 gccjit::context ctxt; 10245 gcc_jit_result *result = NULL; 10246 10247 /* Get a "context" object for working with the library. */ 10248 ctxt = gccjit::context::acquire (); 10249 10250 /* Set some options on the context. 10251 Turn this on to see the code being generated, in assembler form. */ 10252 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 10253 0); 10254 10255 /* Populate the context. */ 10256 create_code (ctxt); 10257 10258 /* Compile the code. */ 10259 result = ctxt.compile (); 10260 10261 ctxt.release (); 10262 10263 if (!result) 10264 @{ 10265 fprintf (stderr, "NULL result"); 10266 return 1; 10267 @} 10268 10269 /* Extract the generated code from "result". */ 10270 typedef int (*loop_test_fn_type) (int); 10271 loop_test_fn_type loop_test = 10272 (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test"); 10273 if (!loop_test) 10274 @{ 10275 fprintf (stderr, "NULL loop_test"); 10276 gcc_jit_result_release (result); 10277 return 1; 10278 @} 10279 10280 /* Run the generated code. */ 10281 int val = loop_test (10); 10282 printf("loop_test returned: %d\n", val); 10283 10284 gcc_jit_result_release (result); 10285 return 0; 10286@} 10287@end example 10288@end quotation 10289 10290Building and running it: 10291 10292@example 10293$ gcc \ 10294 tut03-sum-of-squares.cc \ 10295 -o tut03-sum-of-squares \ 10296 -lgccjit 10297 10298# Run the built program: 10299$ ./tut03-sum-of-squares 10300loop_test returned: 285 10301@end example 10302 10303@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 10304@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 10305@c 10306@c This is free software: you can redistribute it and/or modify it 10307@c under the terms of the GNU General Public License as published by 10308@c the Free Software Foundation, either version 3 of the License, or 10309@c (at your option) any later version. 10310@c 10311@c This program is distributed in the hope that it will be useful, but 10312@c WITHOUT ANY WARRANTY; without even the implied warranty of 10313@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10314@c General Public License for more details. 10315@c 10316@c You should have received a copy of the GNU General Public License 10317@c along with this program. If not, see 10318@c <http://www.gnu.org/licenses/>. 10319 10320@node Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,,Tutorial part 3 Loops and variables<2>,Tutorial<2> 10321@anchor{cp/intro/tutorial04 doc}@anchor{15e}@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{15f} 10322@subsection Tutorial part 4: Adding JIT-compilation to a toy interpreter 10323 10324 10325In this example we construct a “toy” interpreter, and add JIT-compilation 10326to it. 10327 10328@menu 10329* Our toy interpreter: Our toy interpreter<2>. 10330* Compiling to machine code: Compiling to machine code<2>. 10331* Setting things up: Setting things up<2>. 10332* Populating the function: Populating the function<2>. 10333* Verifying the control flow graph: Verifying the control flow graph<2>. 10334* Compiling the context: Compiling the context<2>. 10335* Single-stepping through the generated code: Single-stepping through the generated code<2>. 10336* Examining the generated code: Examining the generated code<2>. 10337* Putting it all together: Putting it all together<2>. 10338* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>. 10339 10340@end menu 10341 10342@node Our toy interpreter<2>,Compiling to machine code<2>,,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> 10343@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{160} 10344@subsubsection Our toy interpreter 10345 10346 10347It’s a stack-based interpreter, and is intended as a (very simple) example 10348of the kind of bytecode interpreter seen in dynamic languages such as 10349Python, Ruby etc. 10350 10351For the sake of simplicity, our toy virtual machine is very limited: 10352 10353@quotation 10354 10355 10356@itemize * 10357 10358@item 10359The only data type is @cite{int} 10360 10361@item 10362It can only work on one function at a time (so that the only 10363function call that can be made is to recurse). 10364 10365@item 10366Functions can only take one parameter. 10367 10368@item 10369Functions have a stack of @cite{int} values. 10370 10371@item 10372We’ll implement function call within the interpreter by calling a 10373function in our implementation, rather than implementing our own 10374frame stack. 10375 10376@item 10377The parser is only good enough to get the examples to work. 10378@end itemize 10379@end quotation 10380 10381Naturally, a real interpreter would be much more complicated that this. 10382 10383The following operations are supported: 10384 10385 10386@multitable {xxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxx} 10387@headitem 10388 10389Operation 10390 10391@tab 10392 10393Meaning 10394 10395@tab 10396 10397Old Stack 10398 10399@tab 10400 10401New Stack 10402 10403@item 10404 10405DUP 10406 10407@tab 10408 10409Duplicate top of stack. 10410 10411@tab 10412 10413@code{[..., x]} 10414 10415@tab 10416 10417@code{[..., x, x]} 10418 10419@item 10420 10421ROT 10422 10423@tab 10424 10425Swap top two elements 10426of stack. 10427 10428@tab 10429 10430@code{[..., x, y]} 10431 10432@tab 10433 10434@code{[..., y, x]} 10435 10436@item 10437 10438BINARY_ADD 10439 10440@tab 10441 10442Add the top two elements 10443on the stack. 10444 10445@tab 10446 10447@code{[..., x, y]} 10448 10449@tab 10450 10451@code{[..., (x+y)]} 10452 10453@item 10454 10455BINARY_SUBTRACT 10456 10457@tab 10458 10459Likewise, but subtract. 10460 10461@tab 10462 10463@code{[..., x, y]} 10464 10465@tab 10466 10467@code{[..., (x-y)]} 10468 10469@item 10470 10471BINARY_MULT 10472 10473@tab 10474 10475Likewise, but multiply. 10476 10477@tab 10478 10479@code{[..., x, y]} 10480 10481@tab 10482 10483@code{[..., (x*y)]} 10484 10485@item 10486 10487BINARY_COMPARE_LT 10488 10489@tab 10490 10491Compare the top two 10492elements on the stack 10493and push a nonzero/zero 10494if (x<y). 10495 10496@tab 10497 10498@code{[..., x, y]} 10499 10500@tab 10501 10502@code{[..., (x<y)]} 10503 10504@item 10505 10506RECURSE 10507 10508@tab 10509 10510Recurse, passing the top 10511of the stack, and 10512popping the result. 10513 10514@tab 10515 10516@code{[..., x]} 10517 10518@tab 10519 10520@code{[..., fn(x)]} 10521 10522@item 10523 10524RETURN 10525 10526@tab 10527 10528Return the top of the 10529stack. 10530 10531@tab 10532 10533@code{[x]} 10534 10535@tab 10536 10537@code{[]} 10538 10539@item 10540 10541PUSH_CONST @cite{arg} 10542 10543@tab 10544 10545Push an int const. 10546 10547@tab 10548 10549@code{[...]} 10550 10551@tab 10552 10553@code{[..., arg]} 10554 10555@item 10556 10557JUMP_ABS_IF_TRUE @cite{arg} 10558 10559@tab 10560 10561Pop; if top of stack was 10562nonzero, jump to 10563@code{arg}. 10564 10565@tab 10566 10567@code{[..., x]} 10568 10569@tab 10570 10571@code{[...]} 10572 10573@end multitable 10574 10575 10576Programs can be interpreted, disassembled, and compiled to machine code. 10577 10578The interpreter reads @code{.toy} scripts. Here’s what a simple recursive 10579factorial program looks like, the script @code{factorial.toy}. 10580The parser ignores lines beginning with a @cite{#}. 10581 10582@quotation 10583 10584@example 10585# Simple recursive factorial implementation, roughly equivalent to: 10586# 10587# int factorial (int arg) 10588# @{ 10589# if (arg < 2) 10590# return arg 10591# return arg * factorial (arg - 1) 10592# @} 10593 10594# Initial state: 10595# stack: [arg] 10596 10597# 0: 10598DUP 10599# stack: [arg, arg] 10600 10601# 1: 10602PUSH_CONST 2 10603# stack: [arg, arg, 2] 10604 10605# 2: 10606BINARY_COMPARE_LT 10607# stack: [arg, (arg < 2)] 10608 10609# 3: 10610JUMP_ABS_IF_TRUE 9 10611# stack: [arg] 10612 10613# 4: 10614DUP 10615# stack: [arg, arg] 10616 10617# 5: 10618PUSH_CONST 1 10619# stack: [arg, arg, 1] 10620 10621# 6: 10622BINARY_SUBTRACT 10623# stack: [arg, (arg - 1) 10624 10625# 7: 10626RECURSE 10627# stack: [arg, factorial(arg - 1)] 10628 10629# 8: 10630BINARY_MULT 10631# stack: [arg * factorial(arg - 1)] 10632 10633# 9: 10634RETURN 10635@end example 10636@end quotation 10637 10638The interpreter is a simple infinite loop with a big @code{switch} statement 10639based on what the next opcode is: 10640 10641@quotation 10642 10643@example 10644 10645int 10646toyvm_function::interpret (int arg, FILE *trace) 10647@{ 10648 toyvm_frame frame; 10649#define PUSH(ARG) (frame.push (ARG)) 10650#define POP(ARG) (frame.pop ()) 10651 10652 frame.frm_function = this; 10653 frame.frm_pc = 0; 10654 frame.frm_cur_depth = 0; 10655 10656 PUSH (arg); 10657 10658 while (1) 10659 @{ 10660 toyvm_op *op; 10661 int x, y; 10662 assert (frame.frm_pc < fn_num_ops); 10663 op = &fn_ops[frame.frm_pc++]; 10664 10665 if (trace) 10666 @{ 10667 frame.dump_stack (trace); 10668 disassemble_op (op, frame.frm_pc, trace); 10669 @} 10670 10671 switch (op->op_opcode) 10672 @{ 10673 /* Ops taking no operand. */ 10674 case DUP: 10675 x = POP (); 10676 PUSH (x); 10677 PUSH (x); 10678 break; 10679 10680 case ROT: 10681 y = POP (); 10682 x = POP (); 10683 PUSH (y); 10684 PUSH (x); 10685 break; 10686 10687 case BINARY_ADD: 10688 y = POP (); 10689 x = POP (); 10690 PUSH (x + y); 10691 break; 10692 10693 case BINARY_SUBTRACT: 10694 y = POP (); 10695 x = POP (); 10696 PUSH (x - y); 10697 break; 10698 10699 case BINARY_MULT: 10700 y = POP (); 10701 x = POP (); 10702 PUSH (x * y); 10703 break; 10704 10705 case BINARY_COMPARE_LT: 10706 y = POP (); 10707 x = POP (); 10708 PUSH (x < y); 10709 break; 10710 10711 case RECURSE: 10712 x = POP (); 10713 x = interpret (x, trace); 10714 PUSH (x); 10715 break; 10716 10717 case RETURN: 10718 return POP (); 10719 10720 /* Ops taking an operand. */ 10721 case PUSH_CONST: 10722 PUSH (op->op_operand); 10723 break; 10724 10725 case JUMP_ABS_IF_TRUE: 10726 x = POP (); 10727 if (x) 10728 frame.frm_pc = op->op_operand; 10729 break; 10730 10731 default: 10732 assert (0); /* unknown opcode */ 10733 10734 @} /* end of switch on opcode */ 10735 @} /* end of while loop */ 10736 10737#undef PUSH 10738#undef POP 10739@} 10740 10741@end example 10742@end quotation 10743 10744@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> 10745@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{161} 10746@subsubsection Compiling to machine code 10747 10748 10749We want to generate machine code that can be cast to this type and 10750then directly executed in-process: 10751 10752@quotation 10753 10754@example 10755typedef int (*toyvm_compiled_func) (int); 10756 10757@end example 10758@end quotation 10759 10760Our compiler isn’t very sophisticated; it takes the implementation of 10761each opcode above, and maps it directly to the operations supported by 10762the libgccjit API. 10763 10764How should we handle the stack? In theory we could calculate what the 10765stack depth will be at each opcode, and optimize away the stack 10766manipulation “by hand”. We’ll see below that libgccjit is able to do 10767this for us, so we’ll implement stack manipulation 10768in a direct way, by creating a @code{stack} array and @code{stack_depth} 10769variables, local within the generated function, equivalent to this C code: 10770 10771@example 10772int stack_depth; 10773int stack[MAX_STACK_DEPTH]; 10774@end example 10775 10776We’ll also have local variables @code{x} and @code{y} for use when implementing 10777the opcodes, equivalent to this: 10778 10779@example 10780int x; 10781int y; 10782@end example 10783 10784This means our compiler has the following state: 10785 10786@quotation 10787 10788@example 10789 10790 toyvm_function &toyvmfn; 10791 10792 gccjit::context ctxt; 10793 10794 gccjit::type int_type; 10795 gccjit::type bool_type; 10796 gccjit::type stack_type; /* int[MAX_STACK_DEPTH] */ 10797 10798 gccjit::rvalue const_one; 10799 10800 gccjit::function fn; 10801 gccjit::param param_arg; 10802 gccjit::lvalue stack; 10803 gccjit::lvalue stack_depth; 10804 gccjit::lvalue x; 10805 gccjit::lvalue y; 10806 10807 gccjit::location op_locs[MAX_OPS]; 10808 gccjit::block initial_block; 10809 gccjit::block op_blocks[MAX_OPS]; 10810 10811@end example 10812@end quotation 10813 10814@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> 10815@anchor{cp/intro/tutorial04 setting-things-up}@anchor{162} 10816@subsubsection Setting things up 10817 10818 10819First we create our types: 10820 10821@quotation 10822 10823@example 10824 10825void 10826compilation_state::create_types () 10827@{ 10828 /* Create types. */ 10829 int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 10830 bool_type = ctxt.get_type (GCC_JIT_TYPE_BOOL); 10831 stack_type = ctxt.new_array_type (int_type, MAX_STACK_DEPTH); 10832 10833@end example 10834@end quotation 10835 10836along with extracting a useful @cite{int} constant: 10837 10838@quotation 10839 10840@example 10841 const_one = ctxt.one (int_type); 10842 10843@} 10844 10845@end example 10846@end quotation 10847 10848We’ll implement push and pop in terms of the @code{stack} array and 10849@code{stack_depth}. Here are helper functions for adding statements to 10850a block, implementing pushing and popping values: 10851 10852@quotation 10853 10854@example 10855 10856void 10857compilation_state::add_push (gccjit::block block, 10858 gccjit::rvalue rvalue, 10859 gccjit::location loc) 10860@{ 10861 /* stack[stack_depth] = RVALUE */ 10862 block.add_assignment ( 10863 /* stack[stack_depth] */ 10864 ctxt.new_array_access ( 10865 stack, 10866 stack_depth, 10867 loc), 10868 rvalue, 10869 loc); 10870 10871 /* "stack_depth++;". */ 10872 block.add_assignment_op ( 10873 stack_depth, 10874 GCC_JIT_BINARY_OP_PLUS, 10875 const_one, 10876 loc); 10877@} 10878 10879void 10880compilation_state::add_pop (gccjit::block block, 10881 gccjit::lvalue lvalue, 10882 gccjit::location loc) 10883@{ 10884 /* "--stack_depth;". */ 10885 block.add_assignment_op ( 10886 stack_depth, 10887 GCC_JIT_BINARY_OP_MINUS, 10888 const_one, 10889 loc); 10890 10891 /* "LVALUE = stack[stack_depth];". */ 10892 block.add_assignment ( 10893 lvalue, 10894 /* stack[stack_depth] */ 10895 ctxt.new_array_access (stack, 10896 stack_depth, 10897 loc), 10898 loc); 10899@} 10900 10901@end example 10902@end quotation 10903 10904We will support single-stepping through the generated code in the 10905debugger, so we need to create @ref{163,,gccjit;;location} instances, one 10906per operation in the source code. These will reference the lines of 10907e.g. @code{factorial.toy}. 10908 10909@quotation 10910 10911@example 10912 10913void 10914compilation_state::create_locations () 10915@{ 10916 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 10917 @{ 10918 toyvm_op *op = &toyvmfn.fn_ops[pc]; 10919 10920 op_locs[pc] = ctxt.new_location (toyvmfn.fn_filename, 10921 op->op_linenum, 10922 0); /* column */ 10923 @} 10924@} 10925 10926@end example 10927@end quotation 10928 10929Let’s create the function itself. As usual, we create its parameter 10930first, then use the parameter to create the function: 10931 10932@quotation 10933 10934@example 10935 10936void 10937compilation_state::create_function (const char *funcname) 10938@{ 10939 std::vector <gccjit::param> params; 10940 param_arg = ctxt.new_param (int_type, "arg", op_locs[0]); 10941 params.push_back (param_arg); 10942 fn = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 10943 int_type, 10944 funcname, 10945 params, 0, 10946 op_locs[0]); 10947 10948@end example 10949@end quotation 10950 10951We create the locals within the function. 10952 10953@quotation 10954 10955@example 10956 stack = fn.new_local (stack_type, "stack"); 10957 stack_depth = fn.new_local (int_type, "stack_depth"); 10958 x = fn.new_local (int_type, "x"); 10959 y = fn.new_local (int_type, "y"); 10960 10961@end example 10962@end quotation 10963 10964@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> 10965@anchor{cp/intro/tutorial04 populating-the-function}@anchor{164} 10966@subsubsection Populating the function 10967 10968 10969There’s some one-time initialization, and the API treats the first block 10970you create as the entrypoint of the function, so we need to create that 10971block first: 10972 10973@quotation 10974 10975@example 10976 initial_block = fn.new_block ("initial"); 10977 10978@end example 10979@end quotation 10980 10981We can now create blocks for each of the operations. Most of these will 10982be consolidated into larger blocks when the optimizer runs. 10983 10984@quotation 10985 10986@example 10987 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 10988 @{ 10989 char buf[16]; 10990 sprintf (buf, "instr%i", pc); 10991 op_blocks[pc] = fn.new_block (buf); 10992 @} 10993 10994@end example 10995@end quotation 10996 10997Now that we have a block it can jump to when it’s done, we can populate 10998the initial block: 10999 11000@quotation 11001 11002@example 11003 11004 /* "stack_depth = 0;". */ 11005 initial_block.add_assignment (stack_depth, 11006 ctxt.zero (int_type), 11007 op_locs[0]); 11008 11009 /* "PUSH (arg);". */ 11010 add_push (initial_block, 11011 param_arg, 11012 op_locs[0]); 11013 11014 /* ...and jump to insn 0. */ 11015 initial_block.end_with_jump (op_blocks[0], 11016 op_locs[0]); 11017 11018@end example 11019@end quotation 11020 11021We can now populate the blocks for the individual operations. We loop 11022through them, adding instructions to their blocks: 11023 11024@quotation 11025 11026@example 11027 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++) 11028 @{ 11029 gccjit::location loc = op_locs[pc]; 11030 11031 gccjit::block block = op_blocks[pc]; 11032 gccjit::block next_block = (pc < toyvmfn.fn_num_ops 11033 ? op_blocks[pc + 1] 11034 : NULL); 11035 11036 toyvm_op *op; 11037 op = &toyvmfn.fn_ops[pc]; 11038 11039@end example 11040@end quotation 11041 11042We’re going to have another big @code{switch} statement for implementing 11043the opcodes, this time for compiling them, rather than interpreting 11044them. It’s helpful to have macros for implementing push and pop, so that 11045we can make the @code{switch} statement that’s coming up look as much as 11046possible like the one above within the interpreter: 11047 11048@example 11049 11050#define X_EQUALS_POP()\ 11051 add_pop (block, x, loc) 11052#define Y_EQUALS_POP()\ 11053 add_pop (block, y, loc) 11054#define PUSH_RVALUE(RVALUE)\ 11055 add_push (block, (RVALUE), loc) 11056#define PUSH_X()\ 11057 PUSH_RVALUE (x) 11058#define PUSH_Y() \ 11059 PUSH_RVALUE (y) 11060 11061@end example 11062 11063@cartouche 11064@quotation Note 11065A particularly clever implementation would have an @emph{identical} 11066@code{switch} statement shared by the interpreter and the compiler, with 11067some preprocessor “magic”. We’re not doing that here, for the sake 11068of simplicity. 11069@end quotation 11070@end cartouche 11071 11072When I first implemented this compiler, I accidentally missed an edit 11073when copying and pasting the @code{Y_EQUALS_POP} macro, so that popping the 11074stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y} 11075uninitialized. 11076 11077To track this kind of thing down, we can use 11078@ref{165,,gccjit;;block;;add_comment()} to add descriptive comments 11079to the internal representation. This is invaluable when looking through 11080the generated IR for, say @code{factorial}: 11081 11082@quotation 11083 11084@example 11085 11086 block.add_comment (opcode_names[op->op_opcode], loc); 11087 11088@end example 11089@end quotation 11090 11091We can now write the big @code{switch} statement that implements the 11092individual opcodes, populating the relevant block with statements: 11093 11094@quotation 11095 11096@example 11097 11098 switch (op->op_opcode) 11099 @{ 11100 case DUP: 11101 X_EQUALS_POP (); 11102 PUSH_X (); 11103 PUSH_X (); 11104 break; 11105 11106 case ROT: 11107 Y_EQUALS_POP (); 11108 X_EQUALS_POP (); 11109 PUSH_Y (); 11110 PUSH_X (); 11111 break; 11112 11113 case BINARY_ADD: 11114 Y_EQUALS_POP (); 11115 X_EQUALS_POP (); 11116 PUSH_RVALUE ( 11117 ctxt.new_binary_op ( 11118 GCC_JIT_BINARY_OP_PLUS, 11119 int_type, 11120 x, y, 11121 loc)); 11122 break; 11123 11124 case BINARY_SUBTRACT: 11125 Y_EQUALS_POP (); 11126 X_EQUALS_POP (); 11127 PUSH_RVALUE ( 11128 ctxt.new_binary_op ( 11129 GCC_JIT_BINARY_OP_MINUS, 11130 int_type, 11131 x, y, 11132 loc)); 11133 break; 11134 11135 case BINARY_MULT: 11136 Y_EQUALS_POP (); 11137 X_EQUALS_POP (); 11138 PUSH_RVALUE ( 11139 ctxt.new_binary_op ( 11140 GCC_JIT_BINARY_OP_MULT, 11141 int_type, 11142 x, y, 11143 loc)); 11144 break; 11145 11146 case BINARY_COMPARE_LT: 11147 Y_EQUALS_POP (); 11148 X_EQUALS_POP (); 11149 PUSH_RVALUE ( 11150 /* cast of bool to int */ 11151 ctxt.new_cast ( 11152 /* (x < y) as a bool */ 11153 ctxt.new_comparison ( 11154 GCC_JIT_COMPARISON_LT, 11155 x, y, 11156 loc), 11157 int_type, 11158 loc)); 11159 break; 11160 11161 case RECURSE: 11162 @{ 11163 X_EQUALS_POP (); 11164 PUSH_RVALUE ( 11165 ctxt.new_call ( 11166 fn, 11167 x, 11168 loc)); 11169 break; 11170 @} 11171 11172 case RETURN: 11173 X_EQUALS_POP (); 11174 block.end_with_return (x, loc); 11175 break; 11176 11177 /* Ops taking an operand. */ 11178 case PUSH_CONST: 11179 PUSH_RVALUE ( 11180 ctxt.new_rvalue (int_type, op->op_operand)); 11181 break; 11182 11183 case JUMP_ABS_IF_TRUE: 11184 X_EQUALS_POP (); 11185 block.end_with_conditional ( 11186 /* "(bool)x". */ 11187 ctxt.new_cast (x, bool_type, loc), 11188 op_blocks[op->op_operand], /* on_true */ 11189 next_block, /* on_false */ 11190 loc); 11191 break; 11192 11193 default: 11194 assert(0); 11195 @} /* end of switch on opcode */ 11196 11197@end example 11198@end quotation 11199 11200Every block must be terminated, via a call to one of the 11201@code{gccjit::block::end_with_} entrypoints. This has been done for two 11202of the opcodes, but we need to do it for the other ones, by jumping 11203to the next block. 11204 11205@quotation 11206 11207@example 11208 if (op->op_opcode != JUMP_ABS_IF_TRUE 11209 && op->op_opcode != RETURN) 11210 block.end_with_jump (next_block, loc); 11211 11212@end example 11213@end quotation 11214 11215This is analogous to simply incrementing the program counter. 11216 11217@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> 11218@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{166} 11219@subsubsection Verifying the control flow graph 11220 11221 11222Having finished looping over the blocks, the context is complete. 11223 11224As before, we can verify that the control flow and statements are sane by 11225using @ref{15c,,gccjit;;function;;dump_to_dot()}: 11226 11227@example 11228fn.dump_to_dot ("/tmp/factorial.dot"); 11229@end example 11230 11231and viewing the result. Note how the label names, comments, and 11232variable names show up in the dump, to make it easier to spot 11233errors in our compiler. 11234 11235@quotation 11236 11237 11238@float Figure 11239 11240@image{libgccjit-figures/factorial,,,image of a control flow graph,png} 11241 11242@end float 11243 11244@end quotation 11245 11246@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> 11247@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{167} 11248@subsubsection Compiling the context 11249 11250 11251Having finished looping over the blocks and populating them with 11252statements, the context is complete. 11253 11254We can now compile it, extract machine code from the result, and 11255run it: 11256 11257@quotation 11258 11259@example 11260 11261class compilation_result 11262@{ 11263public: 11264 compilation_result (gcc_jit_result *result) : 11265 m_result (result) 11266 @{ 11267 @} 11268 ~compilation_result () 11269 @{ 11270 gcc_jit_result_release (m_result); 11271 @} 11272 11273 void *get_code (const char *funcname) 11274 @{ 11275 return gcc_jit_result_get_code (m_result, funcname); 11276 @} 11277 11278private: 11279 gcc_jit_result *m_result; 11280@}; 11281 11282@end example 11283 11284@example 11285 compilation_result compiler_result = fn->compile (); 11286 11287 const char *funcname = fn->get_function_name (); 11288 toyvm_compiled_func code 11289 = (toyvm_compiled_func)compiler_result.get_code (funcname); 11290 11291 printf ("compiler result: %d\n", 11292 code (atoi (argv[2]))); 11293 11294@end example 11295@end quotation 11296 11297@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> 11298@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{168} 11299@subsubsection Single-stepping through the generated code 11300 11301 11302It’s possible to debug the generated code. To do this we need to both: 11303 11304@quotation 11305 11306 11307@itemize * 11308 11309@item 11310Set up source code locations for our statements, so that we can 11311meaningfully step through the code. We did this above by 11312calling @ref{169,,gccjit;;context;;new_location()} and using the 11313results. 11314 11315@item 11316Enable the generation of debugging information, by setting 11317@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 11318@ref{13d,,gccjit;;context} via 11319@ref{149,,gccjit;;context;;set_bool_option()}: 11320 11321@example 11322ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); 11323@end example 11324@end itemize 11325@end quotation 11326 11327Having done this, we can put a breakpoint on the generated function: 11328 11329@example 11330$ gdb --args ./toyvm factorial.toy 10 11331(gdb) break factorial 11332Function "factorial" not defined. 11333Make breakpoint pending on future shared library load? (y or [n]) y 11334Breakpoint 1 (factorial) pending. 11335(gdb) run 11336Breakpoint 1, factorial (arg=10) at factorial.toy:14 1133714 DUP 11338@end example 11339 11340We’ve set up location information, which references @code{factorial.toy}. 11341This allows us to use e.g. @code{list} to see where we are in the script: 11342 11343@example 11344(gdb) list 113459 1134610 # Initial state: 1134711 # stack: [arg] 1134812 1134913 # 0: 1135014 DUP 1135115 # stack: [arg, arg] 1135216 1135317 # 1: 1135418 PUSH_CONST 2 11355@end example 11356 11357and to step through the function, examining the data: 11358 11359@example 11360(gdb) n 1136118 PUSH_CONST 2 11362(gdb) n 1136322 BINARY_COMPARE_LT 11364(gdb) print stack 11365$5 = @{10, 10, 2, 0, -7152, 32767, 0, 0@} 11366(gdb) print stack_depth 11367$6 = 3 11368@end example 11369 11370You’ll see that the parts of the @code{stack} array that haven’t been 11371touched yet are uninitialized. 11372 11373@cartouche 11374@quotation Note 11375Turning on optimizations may lead to unpredictable results when 11376stepping through the generated code: the execution may appear to 11377“jump around” the source code. This is analogous to turning up the 11378optimization level in a regular compiler. 11379@end quotation 11380@end cartouche 11381 11382@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> 11383@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{16a} 11384@subsubsection Examining the generated code 11385 11386 11387How good is the optimized code? 11388 11389We can turn up optimizations, by calling 11390@ref{14a,,gccjit;;context;;set_int_option()} with 11391@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: 11392 11393@example 11394ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); 11395@end example 11396 11397One of GCC’s internal representations is called “gimple”. A dump of the 11398initial gimple representation of the code can be seen by setting: 11399 11400@example 11401ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); 11402@end example 11403 11404With optimization on and source locations displayed, this gives: 11405 11406@c We'll use "c" for gimple dumps 11407 11408@example 11409factorial (signed int arg) 11410@{ 11411 <unnamed type> D.80; 11412 signed int D.81; 11413 signed int D.82; 11414 signed int D.83; 11415 signed int D.84; 11416 signed int D.85; 11417 signed int y; 11418 signed int x; 11419 signed int stack_depth; 11420 signed int stack[8]; 11421 11422 try 11423 @{ 11424 initial: 11425 stack_depth = 0; 11426 stack[stack_depth] = arg; 11427 stack_depth = stack_depth + 1; 11428 goto instr0; 11429 instr0: 11430 /* DUP */: 11431 stack_depth = stack_depth + -1; 11432 x = stack[stack_depth]; 11433 stack[stack_depth] = x; 11434 stack_depth = stack_depth + 1; 11435 stack[stack_depth] = x; 11436 stack_depth = stack_depth + 1; 11437 goto instr1; 11438 instr1: 11439 /* PUSH_CONST */: 11440 stack[stack_depth] = 2; 11441 stack_depth = stack_depth + 1; 11442 goto instr2; 11443 11444 /* etc */ 11445@end example 11446 11447You can see the generated machine code in assembly form via: 11448 11449@example 11450ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1); 11451result = ctxt.compile (); 11452@end example 11453 11454which shows that (on this x86_64 box) the compiler has unrolled the loop 11455and is using MMX instructions to perform several multiplications 11456simultaneously: 11457 11458@example 11459 .file "fake.c" 11460 .text 11461.Ltext0: 11462 .p2align 4,,15 11463 .globl factorial 11464 .type factorial, @@function 11465factorial: 11466.LFB0: 11467 .file 1 "factorial.toy" 11468 .loc 1 14 0 11469 .cfi_startproc 11470.LVL0: 11471.L2: 11472 .loc 1 26 0 11473 cmpl $1, %edi 11474 jle .L13 11475 leal -1(%rdi), %edx 11476 movl %edx, %ecx 11477 shrl $2, %ecx 11478 leal 0(,%rcx,4), %esi 11479 testl %esi, %esi 11480 je .L14 11481 cmpl $9, %edx 11482 jbe .L14 11483 leal -2(%rdi), %eax 11484 movl %eax, -16(%rsp) 11485 leal -3(%rdi), %eax 11486 movd -16(%rsp), %xmm0 11487 movl %edi, -16(%rsp) 11488 movl %eax, -12(%rsp) 11489 movd -16(%rsp), %xmm1 11490 xorl %eax, %eax 11491 movl %edx, -16(%rsp) 11492 movd -12(%rsp), %xmm4 11493 movd -16(%rsp), %xmm6 11494 punpckldq %xmm4, %xmm0 11495 movdqa .LC1(%rip), %xmm4 11496 punpckldq %xmm6, %xmm1 11497 punpcklqdq %xmm0, %xmm1 11498 movdqa .LC0(%rip), %xmm0 11499 jmp .L5 11500 # etc - edited for brevity 11501@end example 11502 11503This is clearly overkill for a function that will likely overflow the 11504@code{int} type before the vectorization is worthwhile - but then again, this 11505is a toy example. 11506 11507Turning down the optimization level to 2: 11508 11509@example 11510ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2); 11511@end example 11512 11513yields this code, which is simple enough to quote in its entirety: 11514 11515@example 11516 .file "fake.c" 11517 .text 11518 .p2align 4,,15 11519 .globl factorial 11520 .type factorial, @@function 11521factorial: 11522.LFB0: 11523 .cfi_startproc 11524.L2: 11525 cmpl $1, %edi 11526 jle .L8 11527 movl $1, %edx 11528 jmp .L4 11529 .p2align 4,,10 11530 .p2align 3 11531.L6: 11532 movl %eax, %edi 11533.L4: 11534.L5: 11535 leal -1(%rdi), %eax 11536 imull %edi, %edx 11537 cmpl $1, %eax 11538 jne .L6 11539.L3: 11540.L7: 11541 imull %edx, %eax 11542 ret 11543.L8: 11544 movl %edi, %eax 11545 movl $1, %edx 11546 jmp .L7 11547 .cfi_endproc 11548.LFE0: 11549 .size factorial, .-factorial 11550 .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%@{gcc_release@})" 11551 .section .note.GNU-stack,"",@@progbits 11552@end example 11553 11554Note that the stack pushing and popping have been eliminated, as has the 11555recursive call (in favor of an iteration). 11556 11557@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> 11558@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{16b} 11559@subsubsection Putting it all together 11560 11561 11562The complete example can be seen in the source tree at 11563@code{gcc/jit/docs/examples/tut04-toyvm/toyvm.cc} 11564 11565along with a Makefile and a couple of sample .toy scripts: 11566 11567@example 11568$ ls -al 11569drwxrwxr-x. 2 david david 4096 Sep 19 17:46 . 11570drwxrwxr-x. 3 david david 4096 Sep 19 15:26 .. 11571-rw-rw-r--. 1 david david 615 Sep 19 12:43 factorial.toy 11572-rw-rw-r--. 1 david david 834 Sep 19 13:08 fibonacci.toy 11573-rw-rw-r--. 1 david david 238 Sep 19 14:22 Makefile 11574-rw-rw-r--. 1 david david 16457 Sep 19 17:07 toyvm.cc 11575 11576$ make toyvm 11577g++ -Wall -g -o toyvm toyvm.cc -lgccjit 11578 11579$ ./toyvm factorial.toy 10 11580interpreter result: 3628800 11581compiler result: 3628800 11582 11583$ ./toyvm fibonacci.toy 10 11584interpreter result: 55 11585compiler result: 55 11586@end example 11587 11588@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> 11589@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{16c} 11590@subsubsection Behind the curtain: How does our code get optimized? 11591 11592 11593Our example is done, but you may be wondering about exactly how the 11594compiler turned what we gave it into the machine code seen above. 11595 11596We can examine what the compiler is doing in detail by setting: 11597 11598@example 11599state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 1); 11600state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 1); 11601@end example 11602 11603This will dump detailed information about the compiler’s state to a 11604directory under @code{/tmp}, and keep it from being cleaned up. 11605 11606The precise names and their formats of these files is subject to change. 11607Higher optimization levels lead to more files. 11608Here’s what I saw (edited for brevity; there were almost 200 files): 11609 11610@example 11611intermediate files written to /tmp/libgccjit-KPQbGw 11612$ ls /tmp/libgccjit-KPQbGw/ 11613fake.c.000i.cgraph 11614fake.c.000i.type-inheritance 11615fake.c.004t.gimple 11616fake.c.007t.omplower 11617fake.c.008t.lower 11618fake.c.011t.eh 11619fake.c.012t.cfg 11620fake.c.014i.visibility 11621fake.c.015i.early_local_cleanups 11622fake.c.016t.ssa 11623# etc 11624@end example 11625 11626The gimple code is converted into Static Single Assignment form, 11627with annotations for use when generating the debuginfo: 11628 11629@example 11630$ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa 11631@end example 11632 11633@example 11634;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11635 11636factorial (signed int arg) 11637@{ 11638 signed int stack[8]; 11639 signed int stack_depth; 11640 signed int x; 11641 signed int y; 11642 <unnamed type> _20; 11643 signed int _21; 11644 signed int _38; 11645 signed int _44; 11646 signed int _51; 11647 signed int _56; 11648 11649initial: 11650 stack_depth_3 = 0; 11651 # DEBUG stack_depth => stack_depth_3 11652 stack[stack_depth_3] = arg_5(D); 11653 stack_depth_7 = stack_depth_3 + 1; 11654 # DEBUG stack_depth => stack_depth_7 11655 # DEBUG instr0 => NULL 11656 # DEBUG /* DUP */ => NULL 11657 stack_depth_8 = stack_depth_7 + -1; 11658 # DEBUG stack_depth => stack_depth_8 11659 x_9 = stack[stack_depth_8]; 11660 # DEBUG x => x_9 11661 stack[stack_depth_8] = x_9; 11662 stack_depth_11 = stack_depth_8 + 1; 11663 # DEBUG stack_depth => stack_depth_11 11664 stack[stack_depth_11] = x_9; 11665 stack_depth_13 = stack_depth_11 + 1; 11666 # DEBUG stack_depth => stack_depth_13 11667 # DEBUG instr1 => NULL 11668 # DEBUG /* PUSH_CONST */ => NULL 11669 stack[stack_depth_13] = 2; 11670 11671 /* etc; edited for brevity */ 11672@end example 11673 11674We can perhaps better see the code by turning off 11675@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} to suppress all those @code{DEBUG} 11676statements, giving: 11677 11678@example 11679$ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa 11680@end example 11681 11682@example 11683;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11684 11685factorial (signed int arg) 11686@{ 11687 signed int stack[8]; 11688 signed int stack_depth; 11689 signed int x; 11690 signed int y; 11691 <unnamed type> _20; 11692 signed int _21; 11693 signed int _38; 11694 signed int _44; 11695 signed int _51; 11696 signed int _56; 11697 11698initial: 11699 stack_depth_3 = 0; 11700 stack[stack_depth_3] = arg_5(D); 11701 stack_depth_7 = stack_depth_3 + 1; 11702 stack_depth_8 = stack_depth_7 + -1; 11703 x_9 = stack[stack_depth_8]; 11704 stack[stack_depth_8] = x_9; 11705 stack_depth_11 = stack_depth_8 + 1; 11706 stack[stack_depth_11] = x_9; 11707 stack_depth_13 = stack_depth_11 + 1; 11708 stack[stack_depth_13] = 2; 11709 stack_depth_15 = stack_depth_13 + 1; 11710 stack_depth_16 = stack_depth_15 + -1; 11711 y_17 = stack[stack_depth_16]; 11712 stack_depth_18 = stack_depth_16 + -1; 11713 x_19 = stack[stack_depth_18]; 11714 _20 = x_19 < y_17; 11715 _21 = (signed int) _20; 11716 stack[stack_depth_18] = _21; 11717 stack_depth_23 = stack_depth_18 + 1; 11718 stack_depth_24 = stack_depth_23 + -1; 11719 x_25 = stack[stack_depth_24]; 11720 if (x_25 != 0) 11721 goto <bb 4> (instr9); 11722 else 11723 goto <bb 3> (instr4); 11724 11725instr4: 11726/* DUP */: 11727 stack_depth_26 = stack_depth_24 + -1; 11728 x_27 = stack[stack_depth_26]; 11729 stack[stack_depth_26] = x_27; 11730 stack_depth_29 = stack_depth_26 + 1; 11731 stack[stack_depth_29] = x_27; 11732 stack_depth_31 = stack_depth_29 + 1; 11733 stack[stack_depth_31] = 1; 11734 stack_depth_33 = stack_depth_31 + 1; 11735 stack_depth_34 = stack_depth_33 + -1; 11736 y_35 = stack[stack_depth_34]; 11737 stack_depth_36 = stack_depth_34 + -1; 11738 x_37 = stack[stack_depth_36]; 11739 _38 = x_37 - y_35; 11740 stack[stack_depth_36] = _38; 11741 stack_depth_40 = stack_depth_36 + 1; 11742 stack_depth_41 = stack_depth_40 + -1; 11743 x_42 = stack[stack_depth_41]; 11744 _44 = factorial (x_42); 11745 stack[stack_depth_41] = _44; 11746 stack_depth_46 = stack_depth_41 + 1; 11747 stack_depth_47 = stack_depth_46 + -1; 11748 y_48 = stack[stack_depth_47]; 11749 stack_depth_49 = stack_depth_47 + -1; 11750 x_50 = stack[stack_depth_49]; 11751 _51 = x_50 * y_48; 11752 stack[stack_depth_49] = _51; 11753 stack_depth_53 = stack_depth_49 + 1; 11754 11755 # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)> 11756instr9: 11757/* RETURN */: 11758 stack_depth_54 = stack_depth_1 + -1; 11759 x_55 = stack[stack_depth_54]; 11760 _56 = x_55; 11761 stack =@{v@} @{CLOBBER@}; 11762 return _56; 11763 11764@} 11765@end example 11766 11767Note in the above how all the @ref{153,,gccjit;;block} instances we 11768created have been consolidated into just 3 blocks in GCC’s internal 11769representation: @code{initial}, @code{instr4} and @code{instr9}. 11770 11771@menu 11772* Optimizing away stack manipulation: Optimizing away stack manipulation<2>. 11773* Elimination of tail recursion: Elimination of tail recursion<2>. 11774 11775@end menu 11776 11777@node Optimizing away stack manipulation<2>,Elimination of tail recursion<2>,,Behind the curtain How does our code get optimized?<2> 11778@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{16d} 11779@subsubsection Optimizing away stack manipulation 11780 11781 11782Recall our simple implementation of stack operations. Let’s examine 11783how the stack operations are optimized away. 11784 11785After a pass of constant-propagation, the depth of the stack at each 11786opcode can be determined at compile-time: 11787 11788@example 11789$ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1 11790@end example 11791 11792@example 11793;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11794 11795factorial (signed int arg) 11796@{ 11797 signed int stack[8]; 11798 signed int stack_depth; 11799 signed int x; 11800 signed int y; 11801 <unnamed type> _20; 11802 signed int _21; 11803 signed int _38; 11804 signed int _44; 11805 signed int _51; 11806 11807initial: 11808 stack[0] = arg_5(D); 11809 x_9 = stack[0]; 11810 stack[0] = x_9; 11811 stack[1] = x_9; 11812 stack[2] = 2; 11813 y_17 = stack[2]; 11814 x_19 = stack[1]; 11815 _20 = x_19 < y_17; 11816 _21 = (signed int) _20; 11817 stack[1] = _21; 11818 x_25 = stack[1]; 11819 if (x_25 != 0) 11820 goto <bb 4> (instr9); 11821 else 11822 goto <bb 3> (instr4); 11823 11824instr4: 11825/* DUP */: 11826 x_27 = stack[0]; 11827 stack[0] = x_27; 11828 stack[1] = x_27; 11829 stack[2] = 1; 11830 y_35 = stack[2]; 11831 x_37 = stack[1]; 11832 _38 = x_37 - y_35; 11833 stack[1] = _38; 11834 x_42 = stack[1]; 11835 _44 = factorial (x_42); 11836 stack[1] = _44; 11837 y_48 = stack[1]; 11838 x_50 = stack[0]; 11839 _51 = x_50 * y_48; 11840 stack[0] = _51; 11841 11842instr9: 11843/* RETURN */: 11844 x_55 = stack[0]; 11845 x_56 = x_55; 11846 stack =@{v@} @{CLOBBER@}; 11847 return x_56; 11848 11849@} 11850@end example 11851 11852Note how, in the above, all those @code{stack_depth} values are now just 11853constants: we’re accessing specific stack locations at each opcode. 11854 11855The “esra” pass (“Early Scalar Replacement of Aggregates”) breaks 11856out our “stack” array into individual elements: 11857 11858@example 11859$ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra 11860@end example 11861 11862@example 11863;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11864 11865Created a replacement for stack offset: 0, size: 32: stack$0 11866Created a replacement for stack offset: 32, size: 32: stack$1 11867Created a replacement for stack offset: 64, size: 32: stack$2 11868 11869Symbols to be put in SSA form 11870@{ D.89 D.90 D.91 @} 11871Incremental SSA update started at block: 0 11872Number of blocks in CFG: 5 11873Number of blocks to update: 4 ( 80%) 11874 11875 11876factorial (signed int arg) 11877@{ 11878 signed int stack$2; 11879 signed int stack$1; 11880 signed int stack$0; 11881 signed int stack[8]; 11882 signed int stack_depth; 11883 signed int x; 11884 signed int y; 11885 <unnamed type> _20; 11886 signed int _21; 11887 signed int _38; 11888 signed int _44; 11889 signed int _51; 11890 11891initial: 11892 stack$0_45 = arg_5(D); 11893 x_9 = stack$0_45; 11894 stack$0_39 = x_9; 11895 stack$1_32 = x_9; 11896 stack$2_30 = 2; 11897 y_17 = stack$2_30; 11898 x_19 = stack$1_32; 11899 _20 = x_19 < y_17; 11900 _21 = (signed int) _20; 11901 stack$1_28 = _21; 11902 x_25 = stack$1_28; 11903 if (x_25 != 0) 11904 goto <bb 4> (instr9); 11905 else 11906 goto <bb 3> (instr4); 11907 11908instr4: 11909/* DUP */: 11910 x_27 = stack$0_39; 11911 stack$0_22 = x_27; 11912 stack$1_14 = x_27; 11913 stack$2_12 = 1; 11914 y_35 = stack$2_12; 11915 x_37 = stack$1_14; 11916 _38 = x_37 - y_35; 11917 stack$1_10 = _38; 11918 x_42 = stack$1_10; 11919 _44 = factorial (x_42); 11920 stack$1_6 = _44; 11921 y_48 = stack$1_6; 11922 x_50 = stack$0_22; 11923 _51 = x_50 * y_48; 11924 stack$0_1 = _51; 11925 11926 # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)> 11927instr9: 11928/* RETURN */: 11929 x_55 = stack$0_52; 11930 x_56 = x_55; 11931 stack =@{v@} @{CLOBBER@}; 11932 return x_56; 11933 11934@} 11935@end example 11936 11937Hence at this point, all those pushes and pops of the stack are now 11938simply assignments to specific temporary variables. 11939 11940After some copy propagation, the stack manipulation has been completely 11941optimized away: 11942 11943@example 11944$ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1 11945@end example 11946 11947@example 11948;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11949 11950factorial (signed int arg) 11951@{ 11952 signed int stack$2; 11953 signed int stack$1; 11954 signed int stack$0; 11955 signed int stack[8]; 11956 signed int stack_depth; 11957 signed int x; 11958 signed int y; 11959 <unnamed type> _20; 11960 signed int _21; 11961 signed int _38; 11962 signed int _44; 11963 signed int _51; 11964 11965initial: 11966 stack$0_39 = arg_5(D); 11967 _20 = arg_5(D) <= 1; 11968 _21 = (signed int) _20; 11969 if (_21 != 0) 11970 goto <bb 4> (instr9); 11971 else 11972 goto <bb 3> (instr4); 11973 11974instr4: 11975/* DUP */: 11976 _38 = arg_5(D) + -1; 11977 _44 = factorial (_38); 11978 _51 = arg_5(D) * _44; 11979 stack$0_1 = _51; 11980 11981 # stack$0_52 = PHI <arg_5(D)(2), _51(3)> 11982instr9: 11983/* RETURN */: 11984 stack =@{v@} @{CLOBBER@}; 11985 return stack$0_52; 11986 11987@} 11988@end example 11989 11990Later on, another pass finally eliminated @code{stack_depth} local and the 11991unused parts of the @cite{stack`} array altogether: 11992 11993@example 11994$ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa 11995@end example 11996 11997@example 11998;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 11999 12000Released 44 names, 314.29%, removed 44 holes 12001factorial (signed int arg) 12002@{ 12003 signed int stack$0; 12004 signed int mult_acc_1; 12005 <unnamed type> _5; 12006 signed int _6; 12007 signed int _7; 12008 signed int mul_tmp_10; 12009 signed int mult_acc_11; 12010 signed int mult_acc_13; 12011 12012 # arg_9 = PHI <arg_8(D)(0)> 12013 # mult_acc_13 = PHI <1(0)> 12014initial: 12015 12016 <bb 5>: 12017 # arg_4 = PHI <arg_9(2), _7(3)> 12018 # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)> 12019 _5 = arg_4 <= 1; 12020 _6 = (signed int) _5; 12021 if (_6 != 0) 12022 goto <bb 4> (instr9); 12023 else 12024 goto <bb 3> (instr4); 12025 12026instr4: 12027/* DUP */: 12028 _7 = arg_4 + -1; 12029 mult_acc_11 = mult_acc_1 * arg_4; 12030 goto <bb 5>; 12031 12032 # stack$0_12 = PHI <arg_4(5)> 12033instr9: 12034/* RETURN */: 12035 mul_tmp_10 = mult_acc_1 * stack$0_12; 12036 return mul_tmp_10; 12037 12038@} 12039@end example 12040 12041@node Elimination of tail recursion<2>,,Optimizing away stack manipulation<2>,Behind the curtain How does our code get optimized?<2> 12042@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{16e} 12043@subsubsection Elimination of tail recursion 12044 12045 12046Another significant optimization is the detection that the call to 12047@code{factorial} is tail recursion, which can be eliminated in favor of 12048an iteration: 12049 12050@example 12051$ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1 12052@end example 12053 12054@example 12055;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0) 12056 12057 12058Symbols to be put in SSA form 12059@{ D.88 @} 12060Incremental SSA update started at block: 0 12061Number of blocks in CFG: 5 12062Number of blocks to update: 4 ( 80%) 12063 12064 12065factorial (signed int arg) 12066@{ 12067 signed int stack$2; 12068 signed int stack$1; 12069 signed int stack$0; 12070 signed int stack[8]; 12071 signed int stack_depth; 12072 signed int x; 12073 signed int y; 12074 signed int mult_acc_1; 12075 <unnamed type> _20; 12076 signed int _21; 12077 signed int _38; 12078 signed int mul_tmp_44; 12079 signed int mult_acc_51; 12080 12081 # arg_5 = PHI <arg_39(D)(0), _38(3)> 12082 # mult_acc_1 = PHI <1(0), mult_acc_51(3)> 12083initial: 12084 _20 = arg_5 <= 1; 12085 _21 = (signed int) _20; 12086 if (_21 != 0) 12087 goto <bb 4> (instr9); 12088 else 12089 goto <bb 3> (instr4); 12090 12091instr4: 12092/* DUP */: 12093 _38 = arg_5 + -1; 12094 mult_acc_51 = mult_acc_1 * arg_5; 12095 goto <bb 2> (initial); 12096 12097 # stack$0_52 = PHI <arg_5(2)> 12098instr9: 12099/* RETURN */: 12100 stack =@{v@} @{CLOBBER@}; 12101 mul_tmp_44 = mult_acc_1 * stack$0_52; 12102 return mul_tmp_44; 12103 12104@} 12105@end example 12106 12107@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 12108@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 12109@c 12110@c This is free software: you can redistribute it and/or modify it 12111@c under the terms of the GNU General Public License as published by 12112@c the Free Software Foundation, either version 3 of the License, or 12113@c (at your option) any later version. 12114@c 12115@c This program is distributed in the hope that it will be useful, but 12116@c WITHOUT ANY WARRANTY; without even the implied warranty of 12117@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12118@c General Public License for more details. 12119@c 12120@c You should have received a copy of the GNU General Public License 12121@c along with this program. If not, see 12122@c <http://www.gnu.org/licenses/>. 12123 12124@node Topic Reference<2>,,Tutorial<2>,C++ bindings for libgccjit 12125@anchor{cp/topics/index doc}@anchor{16f}@anchor{cp/topics/index topic-reference}@anchor{170} 12126@section Topic Reference 12127 12128 12129@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 12130@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 12131@c 12132@c This is free software: you can redistribute it and/or modify it 12133@c under the terms of the GNU General Public License as published by 12134@c the Free Software Foundation, either version 3 of the License, or 12135@c (at your option) any later version. 12136@c 12137@c This program is distributed in the hope that it will be useful, but 12138@c WITHOUT ANY WARRANTY; without even the implied warranty of 12139@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12140@c General Public License for more details. 12141@c 12142@c You should have received a copy of the GNU General Public License 12143@c along with this program. If not, see 12144@c <http://www.gnu.org/licenses/>. 12145 12146@menu 12147* Compilation contexts: Compilation contexts<2>. 12148* Objects: Objects<2>. 12149* Types: Types<2>. 12150* Expressions: Expressions<2>. 12151* Creating and using functions: Creating and using functions<2>. 12152* Source Locations: Source Locations<2>. 12153* Compiling a context: Compiling a context<2>. 12154* Using Assembly Language with libgccjit++:: 12155 12156@end menu 12157 12158@node Compilation contexts<2>,Objects<2>,,Topic Reference<2> 12159@anchor{cp/topics/contexts doc}@anchor{171}@anchor{cp/topics/contexts compilation-contexts}@anchor{172} 12160@subsection Compilation contexts 12161 12162 12163@geindex gccjit;;context (C++ class) 12164@anchor{cp/topics/contexts _CPPv4N6gccjit7contextE}@anchor{13d}@anchor{cp/topics/contexts _CPPv3N6gccjit7contextE}@anchor{173}@anchor{cp/topics/contexts _CPPv2N6gccjit7contextE}@anchor{174}@anchor{cp/topics/contexts gccjit context}@anchor{175} 12165@deffn {C++ Class} gccjit::context 12166@end deffn 12167 12168The top-level of the C++ API is the @ref{13d,,gccjit;;context} type. 12169 12170A @ref{13d,,gccjit;;context} instance encapsulates the state of a 12171compilation. 12172 12173You can set up options on it, and add types, functions and code. 12174Invoking @ref{147,,gccjit;;context;;compile()} on it gives you a 12175@ref{16,,gcc_jit_result *}. 12176 12177It is a thin wrapper around the C API’s @ref{8,,gcc_jit_context *}. 12178 12179@menu 12180* Lifetime-management: Lifetime-management<2>. 12181* Thread-safety: Thread-safety<2>. 12182* Error-handling: Error-handling<3>. 12183* Debugging: Debugging<2>. 12184* Options: Options<4>. 12185 12186@end menu 12187 12188@node Lifetime-management<2>,Thread-safety<2>,,Compilation contexts<2> 12189@anchor{cp/topics/contexts lifetime-management}@anchor{176} 12190@subsubsection Lifetime-management 12191 12192 12193Contexts are the unit of lifetime-management within the API: objects 12194have their lifetime bounded by the context they are created within, and 12195cleanup of such objects is done for you when the context is released. 12196 12197@geindex gccjit;;context;;acquire (C++ function) 12198@anchor{cp/topics/contexts _CPPv4N6gccjit7context7acquireEv}@anchor{13e}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7acquireEv}@anchor{177}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7acquireEv}@anchor{178}@anchor{cp/topics/contexts gccjit context acquire}@anchor{179} 12199@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{13d,,context}::acquire () 12200 12201This function acquires a new @ref{13d,,gccjit;;context} instance, 12202which is independent of any others that may be present within this 12203process. 12204@end deffn 12205 12206@geindex gccjit;;context;;release (C++ function) 12207@anchor{cp/topics/contexts _CPPv4N6gccjit7context7releaseEv}@anchor{141}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7releaseEv}@anchor{17a}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7releaseEv}@anchor{17b}@anchor{cp/topics/contexts gccjit context release}@anchor{17c} 12208@deffn {C++ Function} void gccjit::@ref{13d,,context}::release () 12209 12210This function releases all resources associated with the given context. 12211Both the context itself and all of its @code{gccjit::object *} 12212instances are cleaned up. It should be called exactly once on a given 12213context. 12214 12215It is invalid to use the context or any of its “contextual” objects 12216after calling this. 12217 12218@example 12219ctxt.release (); 12220@end example 12221@end deffn 12222 12223@geindex gccjit;;context;;new_child_context (C++ function) 12224@anchor{cp/topics/contexts _CPPv4N6gccjit7context17new_child_contextEv}@anchor{17d}@anchor{cp/topics/contexts _CPPv3N6gccjit7context17new_child_contextEv}@anchor{17e}@anchor{cp/topics/contexts _CPPv2N6gccjit7context17new_child_contextEv}@anchor{17f}@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{180} 12225@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{13d,,context}::new_child_context () 12226 12227Given an existing JIT context, create a child context. 12228 12229The child inherits a copy of all option-settings from the parent. 12230 12231The child can reference objects created within the parent, but not 12232vice-versa. 12233 12234The lifetime of the child context must be bounded by that of the 12235parent: you should release a child context before releasing the parent 12236context. 12237 12238If you use a function from a parent context within a child context, 12239you have to compile the parent context before you can compile the 12240child context, and the gccjit::result of the parent context must 12241outlive the gccjit::result of the child context. 12242 12243This allows caching of shared initializations. For example, you could 12244create types and declarations of global functions in a parent context 12245once within a process, and then create child contexts whenever a 12246function or loop becomes hot. Each such child context can be used for 12247JIT-compiling just one function or loop, but can reference types 12248and helper functions created within the parent context. 12249 12250Contexts can be arbitrarily nested, provided the above rules are 12251followed, but it’s probably not worth going above 2 or 3 levels, and 12252there will likely be a performance hit for such nesting. 12253@end deffn 12254 12255@node Thread-safety<2>,Error-handling<3>,Lifetime-management<2>,Compilation contexts<2> 12256@anchor{cp/topics/contexts thread-safety}@anchor{181} 12257@subsubsection Thread-safety 12258 12259 12260Instances of @ref{13d,,gccjit;;context} created via 12261@ref{13e,,gccjit;;context;;acquire()} are independent from each other: 12262only one thread may use a given context at once, but multiple threads 12263could each have their own contexts without needing locks. 12264 12265Contexts created via @ref{17d,,gccjit;;context;;new_child_context()} are 12266related to their parent context. They can be partitioned by their 12267ultimate ancestor into independent “family trees”. Only one thread 12268within a process may use a given “family tree” of such contexts at once, 12269and if you’re using multiple threads you should provide your own locking 12270around entire such context partitions. 12271 12272@node Error-handling<3>,Debugging<2>,Thread-safety<2>,Compilation contexts<2> 12273@anchor{cp/topics/contexts error-handling}@anchor{182} 12274@subsubsection Error-handling 12275 12276 12277@c FIXME: How does error-handling work for C++ API? 12278 12279You can only compile and get code from a context if no errors occur. 12280 12281In general, if an error occurs when using an API entrypoint, it returns 12282NULL. You don’t have to check everywhere for NULL results, since the 12283API gracefully handles a NULL being passed in for any argument. 12284 12285Errors are printed on stderr and can be queried using 12286@ref{183,,gccjit;;context;;get_first_error()}. 12287 12288@geindex gccjit;;context;;get_first_error (C++ function) 12289@anchor{cp/topics/contexts _CPPv4N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{183}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{184}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{185}@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{186} 12290@deffn {C++ Function} const char *gccjit::@ref{13d,,context}::get_first_error (gccjit::context *ctxt) 12291 12292Returns the first error message that occurred on the context. 12293 12294The returned string is valid for the rest of the lifetime of the 12295context. 12296 12297If no errors occurred, this will be NULL. 12298@end deffn 12299 12300@node Debugging<2>,Options<4>,Error-handling<3>,Compilation contexts<2> 12301@anchor{cp/topics/contexts debugging}@anchor{187} 12302@subsubsection Debugging 12303 12304 12305@geindex gccjit;;context;;dump_to_file (C++ function) 12306@anchor{cp/topics/contexts _CPPv4N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{188}@anchor{cp/topics/contexts _CPPv3N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{189}@anchor{cp/topics/contexts _CPPv2N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{18a}@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{18b} 12307@deffn {C++ Function} void gccjit::@ref{13d,,context}::dump_to_file (const std::string &path, int update_locations) 12308 12309To help with debugging: dump a C-like representation to the given path, 12310describing what’s been set up on the context. 12311 12312If “update_locations” is true, then also set up @ref{163,,gccjit;;location} 12313information throughout the context, pointing at the dump file as if it 12314were a source file. This may be of use in conjunction with 12315@code{GCCJIT::BOOL_OPTION_DEBUGINFO} to allow stepping through the 12316code in a debugger. 12317@end deffn 12318 12319@geindex gccjit;;context;;dump_reproducer_to_file (C++ function) 12320@anchor{cp/topics/contexts _CPPv4N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18c}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18d}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18e}@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{18f} 12321@deffn {C++ Function} void gccjit::@ref{13d,,context}::dump_reproducer_to_file (gcc_jit_context *ctxt, const char *path) 12322 12323This is a thin wrapper around the C API 12324@ref{5d,,gcc_jit_context_dump_reproducer_to_file()}, and hence works the 12325same way. 12326 12327Note that the generated source is C code, not C++; this might be of use 12328for seeing what the C++ bindings are doing at the C level. 12329@end deffn 12330 12331@node Options<4>,,Debugging<2>,Compilation contexts<2> 12332@anchor{cp/topics/contexts options}@anchor{190} 12333@subsubsection Options 12334 12335 12336@menu 12337* String Options: String Options<2>. 12338* Boolean options: Boolean options<2>. 12339* Integer options: Integer options<2>. 12340* Additional command-line options: Additional command-line options<2>. 12341 12342@end menu 12343 12344@node String Options<2>,Boolean options<2>,,Options<4> 12345@anchor{cp/topics/contexts string-options}@anchor{191} 12346@subsubsection String Options 12347 12348 12349@geindex gccjit;;context;;set_str_option (C++ function) 12350@anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{192}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{193}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{194}@anchor{cp/topics/contexts gccjit context set_str_option__gcc_jit_str_option cCP}@anchor{195} 12351@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_str_option (enum gcc_jit_str_option, const char *value) 12352 12353Set a string option of the context. 12354 12355This is a thin wrapper around the C API 12356@ref{61,,gcc_jit_context_set_str_option()}; the options have the same 12357meaning. 12358@end deffn 12359 12360@node Boolean options<2>,Integer options<2>,String Options<2>,Options<4> 12361@anchor{cp/topics/contexts boolean-options}@anchor{196} 12362@subsubsection Boolean options 12363 12364 12365@geindex gccjit;;context;;set_bool_option (C++ function) 12366@anchor{cp/topics/contexts _CPPv4N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{149}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{197}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{198}@anchor{cp/topics/contexts gccjit context set_bool_option__gcc_jit_bool_option i}@anchor{199} 12367@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_option (enum gcc_jit_bool_option, int value) 12368 12369Set a boolean option of the context. 12370 12371This is a thin wrapper around the C API 12372@ref{1b,,gcc_jit_context_set_bool_option()}; the options have the same 12373meaning. 12374@end deffn 12375 12376@geindex gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function) 12377@anchor{cp/topics/contexts _CPPv4N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19a}@anchor{cp/topics/contexts _CPPv3N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19b}@anchor{cp/topics/contexts _CPPv2N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19c}@anchor{cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i}@anchor{19d} 12378@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_allow_unreachable_blocks (int bool_value) 12379 12380By default, libgccjit will issue an error about unreachable blocks 12381within a function. 12382 12383This entrypoint can be used to disable that error; it is a thin wrapper 12384around the C API 12385@ref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()}. 12386 12387This entrypoint was added in @ref{6c,,LIBGCCJIT_ABI_2}; you can test for 12388its presence using 12389 12390@example 12391#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks 12392@end example 12393@end deffn 12394 12395@geindex gccjit;;context;;set_bool_use_external_driver (C++ function) 12396@anchor{cp/topics/contexts _CPPv4N6gccjit7context28set_bool_use_external_driverEi}@anchor{19e}@anchor{cp/topics/contexts _CPPv3N6gccjit7context28set_bool_use_external_driverEi}@anchor{19f}@anchor{cp/topics/contexts _CPPv2N6gccjit7context28set_bool_use_external_driverEi}@anchor{1a0}@anchor{cp/topics/contexts gccjit context set_bool_use_external_driver__i}@anchor{1a1} 12397@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_use_external_driver (int bool_value) 12398 12399libgccjit internally generates assembler, and uses “driver” code 12400for converting it to other formats (e.g. shared libraries). 12401 12402By default, libgccjit will use an embedded copy of the driver 12403code. 12404 12405This option can be used to instead invoke an external driver executable 12406as a subprocess; it is a thin wrapper around the C API 12407@ref{6d,,gcc_jit_context_set_bool_use_external_driver()}. 12408 12409This entrypoint was added in @ref{6e,,LIBGCCJIT_ABI_5}; you can test for 12410its presence using 12411 12412@example 12413#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver 12414@end example 12415@end deffn 12416 12417@node Integer options<2>,Additional command-line options<2>,Boolean options<2>,Options<4> 12418@anchor{cp/topics/contexts integer-options}@anchor{1a2} 12419@subsubsection Integer options 12420 12421 12422@geindex gccjit;;context;;set_int_option (C++ function) 12423@anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{14a}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1a3}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1a4}@anchor{cp/topics/contexts gccjit context set_int_option__gcc_jit_int_option i}@anchor{1a5} 12424@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_int_option (enum gcc_jit_int_option, int value) 12425 12426Set an integer option of the context. 12427 12428This is a thin wrapper around the C API 12429@ref{1e,,gcc_jit_context_set_int_option()}; the options have the same 12430meaning. 12431@end deffn 12432 12433@node Additional command-line options<2>,,Integer options<2>,Options<4> 12434@anchor{cp/topics/contexts additional-command-line-options}@anchor{1a6} 12435@subsubsection Additional command-line options 12436 12437 12438@geindex gccjit;;context;;add_command_line_option (C++ function) 12439@anchor{cp/topics/contexts _CPPv4N6gccjit7context23add_command_line_optionEPKc}@anchor{1a7}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23add_command_line_optionEPKc}@anchor{1a8}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23add_command_line_optionEPKc}@anchor{1a9}@anchor{cp/topics/contexts gccjit context add_command_line_option__cCP}@anchor{1aa} 12440@deffn {C++ Function} void gccjit::@ref{13d,,context}::add_command_line_option (const char *optname) 12441 12442Add an arbitrary gcc command-line option to the context for use 12443when compiling. 12444 12445This is a thin wrapper around the C API 12446@ref{72,,gcc_jit_context_add_command_line_option()}. 12447 12448This entrypoint was added in @ref{73,,LIBGCCJIT_ABI_1}; you can test for 12449its presence using 12450 12451@example 12452#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option 12453@end example 12454@end deffn 12455 12456@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 12457@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 12458@c 12459@c This is free software: you can redistribute it and/or modify it 12460@c under the terms of the GNU General Public License as published by 12461@c the Free Software Foundation, either version 3 of the License, or 12462@c (at your option) any later version. 12463@c 12464@c This program is distributed in the hope that it will be useful, but 12465@c WITHOUT ANY WARRANTY; without even the implied warranty of 12466@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12467@c General Public License for more details. 12468@c 12469@c You should have received a copy of the GNU General Public License 12470@c along with this program. If not, see 12471@c <http://www.gnu.org/licenses/>. 12472 12473@node Objects<2>,Types<2>,Compilation contexts<2>,Topic Reference<2> 12474@anchor{cp/topics/objects doc}@anchor{1ab}@anchor{cp/topics/objects objects}@anchor{1ac} 12475@subsection Objects 12476 12477 12478@geindex gccjit;;object (C++ class) 12479@anchor{cp/topics/objects _CPPv4N6gccjit6objectE}@anchor{142}@anchor{cp/topics/objects _CPPv3N6gccjit6objectE}@anchor{1ad}@anchor{cp/topics/objects _CPPv2N6gccjit6objectE}@anchor{1ae}@anchor{cp/topics/objects gccjit object}@anchor{1af} 12480@deffn {C++ Class} gccjit::object 12481@end deffn 12482 12483Almost every entity in the API (with the exception of 12484@ref{13d,,gccjit;;context} and @ref{16,,gcc_jit_result *}) is a 12485“contextual” object, a @ref{142,,gccjit;;object}. 12486 12487A JIT object: 12488 12489@quotation 12490 12491 12492@itemize * 12493 12494@item 12495is associated with a @ref{13d,,gccjit;;context}. 12496 12497@item 12498is automatically cleaned up for you when its context is released so 12499you don’t need to manually track and cleanup all objects, just the 12500contexts. 12501@end itemize 12502@end quotation 12503 12504The C++ class hierarchy within the @code{gccjit} namespace looks like this: 12505 12506@example 12507+- object 12508 +- location 12509 +- type 12510 +- struct 12511 +- field 12512 +- function 12513 +- block 12514 +- rvalue 12515 +- lvalue 12516 +- param 12517 +- case_ 12518@end example 12519 12520The @ref{142,,gccjit;;object} base class has the following operations: 12521 12522@geindex gccjit;;object;;get_context (C++ function) 12523@anchor{cp/topics/objects _CPPv4NK6gccjit6object11get_contextEv}@anchor{1b0}@anchor{cp/topics/objects _CPPv3NK6gccjit6object11get_contextEv}@anchor{1b1}@anchor{cp/topics/objects _CPPv2NK6gccjit6object11get_contextEv}@anchor{1b2}@anchor{cp/topics/objects gccjit object get_contextC}@anchor{1b3} 12524@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{142,,object}::get_context () const 12525 12526Which context is the obj within? 12527@end deffn 12528 12529@geindex gccjit;;object;;get_debug_string (C++ function) 12530@anchor{cp/topics/objects _CPPv4NK6gccjit6object16get_debug_stringEv}@anchor{143}@anchor{cp/topics/objects _CPPv3NK6gccjit6object16get_debug_stringEv}@anchor{1b4}@anchor{cp/topics/objects _CPPv2NK6gccjit6object16get_debug_stringEv}@anchor{1b5}@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{1b6} 12531@deffn {C++ Function} std::string gccjit::@ref{142,,object}::get_debug_string () const 12532 12533Generate a human-readable description for the given object. 12534 12535For example, 12536 12537@example 12538printf ("obj: %s\n", obj.get_debug_string ().c_str ()); 12539@end example 12540 12541might give this text on stdout: 12542 12543@example 12544obj: 4.0 * (float)i 12545@end example 12546@end deffn 12547 12548@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 12549@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 12550@c 12551@c This is free software: you can redistribute it and/or modify it 12552@c under the terms of the GNU General Public License as published by 12553@c the Free Software Foundation, either version 3 of the License, or 12554@c (at your option) any later version. 12555@c 12556@c This program is distributed in the hope that it will be useful, but 12557@c WITHOUT ANY WARRANTY; without even the implied warranty of 12558@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12559@c General Public License for more details. 12560@c 12561@c You should have received a copy of the GNU General Public License 12562@c along with this program. If not, see 12563@c <http://www.gnu.org/licenses/>. 12564 12565@node Types<2>,Expressions<2>,Objects<2>,Topic Reference<2> 12566@anchor{cp/topics/types doc}@anchor{1b7}@anchor{cp/topics/types types}@anchor{1b8} 12567@subsection Types 12568 12569 12570@geindex gccjit;;type (C++ class) 12571@anchor{cp/topics/types _CPPv4N6gccjit4typeE}@anchor{13f}@anchor{cp/topics/types _CPPv3N6gccjit4typeE}@anchor{1b9}@anchor{cp/topics/types _CPPv2N6gccjit4typeE}@anchor{1ba}@anchor{cp/topics/types gccjit type}@anchor{1bb} 12572@deffn {C++ Class} gccjit::type 12573 12574gccjit::type represents a type within the library. It is a subclass 12575of @ref{142,,gccjit;;object}. 12576@end deffn 12577 12578Types can be created in several ways: 12579 12580 12581@itemize * 12582 12583@item 12584fundamental types can be accessed using 12585@ref{140,,gccjit;;context;;get_type()}: 12586 12587@example 12588gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); 12589@end example 12590 12591or using the @code{gccjit::context::get_int_type} template: 12592 12593@example 12594gccjit::type t = ctxt.get_int_type <unsigned short> (); 12595@end example 12596 12597See @ref{b,,gcc_jit_context_get_type()} for the available types. 12598 12599@item 12600derived types can be accessed by using functions such as 12601@ref{1bc,,gccjit;;type;;get_pointer()} and @ref{1bd,,gccjit;;type;;get_const()}: 12602 12603@example 12604gccjit::type const_int_star = int_type.get_const ().get_pointer (); 12605gccjit::type int_const_star = int_type.get_pointer ().get_const (); 12606@end example 12607 12608@item 12609by creating structures (see below). 12610@end itemize 12611 12612@menu 12613* Standard types: Standard types<2>. 12614* Pointers@comma{} const@comma{} and volatile: Pointers const and volatile<2>. 12615* Vector types: Vector types<2>. 12616* Structures and unions: Structures and unions<2>. 12617 12618@end menu 12619 12620@node Standard types<2>,Pointers const and volatile<2>,,Types<2> 12621@anchor{cp/topics/types standard-types}@anchor{1be} 12622@subsubsection Standard types 12623 12624 12625@geindex gccjit;;context;;get_type (C++ function) 12626@anchor{cp/topics/types _CPPv4N6gccjit7context8get_typeE13gcc_jit_types}@anchor{140}@anchor{cp/topics/types _CPPv3N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1bf}@anchor{cp/topics/types _CPPv2N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1c0}@anchor{cp/topics/types gccjit context get_type__gcc_jit_types}@anchor{1c1} 12627@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_type (enum gcc_jit_types) 12628 12629Access a specific type. This is a thin wrapper around 12630@ref{b,,gcc_jit_context_get_type()}; the parameter has the same meaning. 12631@end deffn 12632 12633@geindex gccjit;;context;;get_int_type (C++ function) 12634@anchor{cp/topics/types _CPPv4N6gccjit7context12get_int_typeE6size_ti}@anchor{1c2}@anchor{cp/topics/types _CPPv3N6gccjit7context12get_int_typeE6size_ti}@anchor{1c3}@anchor{cp/topics/types _CPPv2N6gccjit7context12get_int_typeE6size_ti}@anchor{1c4}@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{1c5} 12635@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_int_type (size_t num_bytes, int is_signed) 12636 12637Access the integer type of the given size. 12638@end deffn 12639 12640@geindex gccjit;;context;;get_int_type<T> (C++ function) 12641@anchor{cp/topics/types _CPPv4IEN6gccjit7context12get_int_typeI1TEEN6gccjit4typeEv}@anchor{1c6}@anchor{cp/topics/types _CPPv3IEN6gccjit7context12get_int_typeI1TEEv}@anchor{1c7}@anchor{cp/topics/types _CPPv2IEN6gccjit7context12get_int_typeI1TEEv}@anchor{1c8} 12642@deffn {C++ Function} template<>gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_int_type<T> () 12643 12644Access the given integer type. For example, you could map the 12645@code{unsigned short} type into a gccjit::type via: 12646 12647@example 12648gccjit::type t = ctxt.get_int_type <unsigned short> (); 12649@end example 12650@end deffn 12651 12652@node Pointers const and volatile<2>,Vector types<2>,Standard types<2>,Types<2> 12653@anchor{cp/topics/types pointers-const-and-volatile}@anchor{1c9} 12654@subsubsection Pointers, @cite{const}, and @cite{volatile} 12655 12656 12657@geindex gccjit;;type;;get_pointer (C++ function) 12658@anchor{cp/topics/types _CPPv4N6gccjit4type11get_pointerEv}@anchor{1bc}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_pointerEv}@anchor{1ca}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_pointerEv}@anchor{1cb}@anchor{cp/topics/types gccjit type get_pointer}@anchor{1cc} 12659@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_pointer () 12660 12661Given type “T”, get type “T*”. 12662@end deffn 12663 12664@geindex gccjit;;type;;get_const (C++ function) 12665@anchor{cp/topics/types _CPPv4N6gccjit4type9get_constEv}@anchor{1bd}@anchor{cp/topics/types _CPPv3N6gccjit4type9get_constEv}@anchor{1cd}@anchor{cp/topics/types _CPPv2N6gccjit4type9get_constEv}@anchor{1ce}@anchor{cp/topics/types gccjit type get_const}@anchor{1cf} 12666@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_const () 12667 12668Given type “T”, get type “const T”. 12669@end deffn 12670 12671@geindex gccjit;;type;;get_volatile (C++ function) 12672@anchor{cp/topics/types _CPPv4N6gccjit4type12get_volatileEv}@anchor{1d0}@anchor{cp/topics/types _CPPv3N6gccjit4type12get_volatileEv}@anchor{1d1}@anchor{cp/topics/types _CPPv2N6gccjit4type12get_volatileEv}@anchor{1d2}@anchor{cp/topics/types gccjit type get_volatile}@anchor{1d3} 12673@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_volatile () 12674 12675Given type “T”, get type “volatile T”. 12676@end deffn 12677 12678@geindex gccjit;;type;;get_aligned (C++ function) 12679@anchor{cp/topics/types _CPPv4N6gccjit4type11get_alignedE6size_t}@anchor{1d4}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_alignedE6size_t}@anchor{1d5}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_alignedE6size_t}@anchor{1d6}@anchor{cp/topics/types gccjit type get_aligned__s}@anchor{1d7} 12680@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_aligned (size_t alignment_in_bytes) 12681 12682Given type “T”, get type: 12683 12684@example 12685T __attribute__ ((aligned (ALIGNMENT_IN_BYTES))) 12686@end example 12687 12688The alignment must be a power of two. 12689@end deffn 12690 12691@geindex gccjit;;context;;new_array_type (C++ function) 12692@anchor{cp/topics/types _CPPv4N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1d8}@anchor{cp/topics/types _CPPv3N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1d9}@anchor{cp/topics/types _CPPv2N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1da}@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{1db} 12693@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc) 12694 12695Given type “T”, get type “T[N]” (for a constant N). 12696Param “loc” is optional. 12697@end deffn 12698 12699@node Vector types<2>,Structures and unions<2>,Pointers const and volatile<2>,Types<2> 12700@anchor{cp/topics/types vector-types}@anchor{1dc} 12701@subsubsection Vector types 12702 12703 12704@geindex gccjit;;type;;get_vector (C++ function) 12705@anchor{cp/topics/types _CPPv4N6gccjit4type10get_vectorE6size_t}@anchor{1dd}@anchor{cp/topics/types _CPPv3N6gccjit4type10get_vectorE6size_t}@anchor{1de}@anchor{cp/topics/types _CPPv2N6gccjit4type10get_vectorE6size_t}@anchor{1df}@anchor{cp/topics/types gccjit type get_vector__s}@anchor{1e0} 12706@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_vector (size_t num_units) 12707 12708Given type “T”, get type: 12709 12710@example 12711T __attribute__ ((vector_size (sizeof(T) * num_units)) 12712@end example 12713 12714T must be integral or floating point; num_units must be a power of two. 12715@end deffn 12716 12717@node Structures and unions<2>,,Vector types<2>,Types<2> 12718@anchor{cp/topics/types structures-and-unions}@anchor{1e1} 12719@subsubsection Structures and unions 12720 12721 12722@geindex gccjit;;struct_ (C++ class) 12723@anchor{cp/topics/types _CPPv4N6gccjit7struct_E}@anchor{1e2}@anchor{cp/topics/types _CPPv3N6gccjit7struct_E}@anchor{1e3}@anchor{cp/topics/types _CPPv2N6gccjit7struct_E}@anchor{1e4}@anchor{cp/topics/types gccjit struct_}@anchor{1e5} 12724@deffn {C++ Class} gccjit::struct_ 12725@end deffn 12726 12727A compound type analagous to a C @cite{struct}. 12728 12729@ref{1e2,,gccjit;;struct_} is a subclass of @ref{13f,,gccjit;;type} (and thus 12730of @ref{142,,gccjit;;object} in turn). 12731 12732@geindex gccjit;;field (C++ class) 12733@anchor{cp/topics/types _CPPv4N6gccjit5fieldE}@anchor{1e6}@anchor{cp/topics/types _CPPv3N6gccjit5fieldE}@anchor{1e7}@anchor{cp/topics/types _CPPv2N6gccjit5fieldE}@anchor{1e8}@anchor{cp/topics/types gccjit field}@anchor{1e9} 12734@deffn {C++ Class} gccjit::field 12735@end deffn 12736 12737A field within a @ref{1e2,,gccjit;;struct_}. 12738 12739@ref{1e6,,gccjit;;field} is a subclass of @ref{142,,gccjit;;object}. 12740 12741You can model C @cite{struct} types by creating @ref{1e2,,gccjit;;struct_} and 12742@ref{1e6,,gccjit;;field} instances, in either order: 12743 12744 12745@itemize * 12746 12747@item 12748by creating the fields, then the structure. For example, to model: 12749 12750@example 12751struct coord @{double x; double y; @}; 12752@end example 12753 12754you could call: 12755 12756@example 12757gccjit::field field_x = ctxt.new_field (double_type, "x"); 12758gccjit::field field_y = ctxt.new_field (double_type, "y"); 12759std::vector fields; 12760fields.push_back (field_x); 12761fields.push_back (field_y); 12762gccjit::struct_ coord = ctxt.new_struct_type ("coord", fields); 12763@end example 12764 12765@item 12766by creating the structure, then populating it with fields, typically 12767to allow modelling self-referential structs such as: 12768 12769@example 12770struct node @{ int m_hash; struct node *m_next; @}; 12771@end example 12772 12773like this: 12774 12775@example 12776gccjit::struct_ node = ctxt.new_opaque_struct_type ("node"); 12777gccjit::type node_ptr = node.get_pointer (); 12778gccjit::field field_hash = ctxt.new_field (int_type, "m_hash"); 12779gccjit::field field_next = ctxt.new_field (node_ptr, "m_next"); 12780std::vector fields; 12781fields.push_back (field_hash); 12782fields.push_back (field_next); 12783node.set_fields (fields); 12784@end example 12785@end itemize 12786 12787@c FIXME: the above API doesn't seem to exist yet 12788 12789@geindex gccjit;;context;;new_field (C++ function) 12790@anchor{cp/topics/types _CPPv4N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1ea}@anchor{cp/topics/types _CPPv3N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1eb}@anchor{cp/topics/types _CPPv2N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1ec}@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{1ed} 12791@deffn {C++ Function} gccjit::@ref{1e6,,field} gccjit::@ref{13d,,context}::new_field (gccjit::type type, const char *name, gccjit::location loc) 12792 12793Construct a new field, with the given type and name. 12794@end deffn 12795 12796@geindex gccjit;;context;;new_struct_type (C++ function) 12797@anchor{cp/topics/types _CPPv4N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1ee}@anchor{cp/topics/types _CPPv3N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1ef}@anchor{cp/topics/types _CPPv2N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1f0}@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{1f1} 12798@deffn {C++ Function} gccjit::@ref{1e2,,struct_} gccjit::@ref{13d,,context}::new_struct_type (const std::string &name, std::vector<field> &fields, gccjit::location loc) 12799 12800@quotation 12801 12802Construct a new struct type, with the given name and fields. 12803@end quotation 12804@end deffn 12805 12806@geindex gccjit;;context;;new_opaque_struct (C++ function) 12807@anchor{cp/topics/types _CPPv4N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f2}@anchor{cp/topics/types _CPPv3N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f3}@anchor{cp/topics/types _CPPv2N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f4}@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{1f5} 12808@deffn {C++ Function} gccjit::@ref{1e2,,struct_} gccjit::@ref{13d,,context}::new_opaque_struct (const std::string &name, gccjit::location loc) 12809 12810Construct a new struct type, with the given name, but without 12811specifying the fields. The fields can be omitted (in which case the 12812size of the struct is not known), or later specified using 12813@ref{91,,gcc_jit_struct_set_fields()}. 12814@end deffn 12815 12816@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 12817@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 12818@c 12819@c This is free software: you can redistribute it and/or modify it 12820@c under the terms of the GNU General Public License as published by 12821@c the Free Software Foundation, either version 3 of the License, or 12822@c (at your option) any later version. 12823@c 12824@c This program is distributed in the hope that it will be useful, but 12825@c WITHOUT ANY WARRANTY; without even the implied warranty of 12826@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12827@c General Public License for more details. 12828@c 12829@c You should have received a copy of the GNU General Public License 12830@c along with this program. If not, see 12831@c <http://www.gnu.org/licenses/>. 12832 12833@node Expressions<2>,Creating and using functions<2>,Types<2>,Topic Reference<2> 12834@anchor{cp/topics/expressions doc}@anchor{1f6}@anchor{cp/topics/expressions expressions}@anchor{1f7} 12835@subsection Expressions 12836 12837 12838@menu 12839* Rvalues: Rvalues<2>. 12840* Lvalues: Lvalues<2>. 12841* Working with pointers@comma{} structs and unions: Working with pointers structs and unions<2>. 12842 12843@end menu 12844 12845@node Rvalues<2>,Lvalues<2>,,Expressions<2> 12846@anchor{cp/topics/expressions rvalues}@anchor{1f8} 12847@subsubsection Rvalues 12848 12849 12850@geindex gccjit;;rvalue (C++ class) 12851@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalueE}@anchor{146}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalueE}@anchor{1f9}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalueE}@anchor{1fa}@anchor{cp/topics/expressions gccjit rvalue}@anchor{1fb} 12852@deffn {C++ Class} gccjit::rvalue 12853@end deffn 12854 12855A @ref{146,,gccjit;;rvalue} is an expression that can be computed. It is a 12856subclass of @ref{142,,gccjit;;object}, and is a thin wrapper around 12857@ref{13,,gcc_jit_rvalue *} from the C API. 12858 12859It can be simple, e.g.: 12860 12861@quotation 12862 12863 12864@itemize * 12865 12866@item 12867an integer value e.g. @cite{0} or @cite{42} 12868 12869@item 12870a string literal e.g. @cite{“Hello world”} 12871 12872@item 12873a variable e.g. @cite{i}. These are also lvalues (see below). 12874@end itemize 12875@end quotation 12876 12877or compound e.g.: 12878 12879@quotation 12880 12881 12882@itemize * 12883 12884@item 12885a unary expression e.g. @cite{!cond} 12886 12887@item 12888a binary expression e.g. @cite{(a + b)} 12889 12890@item 12891a function call e.g. @cite{get_distance (&player_ship@comma{} &target)} 12892 12893@item 12894etc. 12895@end itemize 12896@end quotation 12897 12898Every rvalue has an associated type, and the API will check to ensure 12899that types match up correctly (otherwise the context will emit an error). 12900 12901@geindex gccjit;;rvalue;;get_type (C++ function) 12902@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue8get_typeEv}@anchor{1fc}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue8get_typeEv}@anchor{1fd}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue8get_typeEv}@anchor{1fe}@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{1ff} 12903@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{146,,rvalue}::get_type () 12904 12905Get the type of this rvalue. 12906@end deffn 12907 12908@menu 12909* Simple expressions: Simple expressions<2>. 12910* Vector expressions: Vector expressions<2>. 12911* Unary Operations: Unary Operations<2>. 12912* Binary Operations: Binary Operations<2>. 12913* Comparisons: Comparisons<2>. 12914* Function calls: Function calls<2>. 12915* Function pointers: Function pointers<3>. 12916* Type-coercion: Type-coercion<2>. 12917 12918@end menu 12919 12920@node Simple expressions<2>,Vector expressions<2>,,Rvalues<2> 12921@anchor{cp/topics/expressions simple-expressions}@anchor{200} 12922@subsubsection Simple expressions 12923 12924 12925@geindex gccjit;;context;;new_rvalue (C++ function) 12926@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{15a}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{201}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{202}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{203} 12927@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, int value) const 12928 12929Given a numeric type (integer or floating point), build an rvalue for 12930the given constant @code{int} value. 12931@end deffn 12932 12933@geindex gccjit;;context;;new_rvalue (C++ function) 12934@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{204}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{205}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{206}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{207} 12935@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, long value) const 12936 12937Given a numeric type (integer or floating point), build an rvalue for 12938the given constant @code{long} value. 12939@end deffn 12940 12941@geindex gccjit;;context;;zero (C++ function) 12942@anchor{cp/topics/expressions _CPPv4NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{156}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{208}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{209}@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{20a} 12943@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::zero (gccjit::type numeric_type) const 12944 12945Given a numeric type (integer or floating point), get the rvalue for 12946zero. Essentially this is just a shortcut for: 12947 12948@example 12949ctxt.new_rvalue (numeric_type, 0) 12950@end example 12951@end deffn 12952 12953@geindex gccjit;;context;;one (C++ function) 12954@anchor{cp/topics/expressions _CPPv4NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20b}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20c}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20d}@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{20e} 12955@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::one (gccjit::type numeric_type) const 12956 12957Given a numeric type (integer or floating point), get the rvalue for 12958one. Essentially this is just a shortcut for: 12959 12960@example 12961ctxt.new_rvalue (numeric_type, 1) 12962@end example 12963@end deffn 12964 12965@geindex gccjit;;context;;new_rvalue (C++ function) 12966@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{20f}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{210}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{211}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{212} 12967@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, double value) const 12968 12969Given a numeric type (integer or floating point), build an rvalue for 12970the given constant @code{double} value. 12971@end deffn 12972 12973@geindex gccjit;;context;;new_rvalue (C++ function) 12974@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{213}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{214}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{215}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{216} 12975@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type pointer_type, void *value) const 12976 12977Given a pointer type, build an rvalue for the given address. 12978@end deffn 12979 12980@geindex gccjit;;context;;new_rvalue (C++ function) 12981@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{217}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{218}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{219}@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{21a} 12982@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (const std::string &value) const 12983 12984Generate an rvalue of type @code{GCC_JIT_TYPE_CONST_CHAR_PTR} for 12985the given string. This is akin to a string literal. 12986@end deffn 12987 12988@node Vector expressions<2>,Unary Operations<2>,Simple expressions<2>,Rvalues<2> 12989@anchor{cp/topics/expressions vector-expressions}@anchor{21b} 12990@subsubsection Vector expressions 12991 12992 12993@geindex gccjit;;context;;new_rvalue (C++ function) 12994@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21c}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21d}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21e}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C}@anchor{21f} 12995@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type vector_type, std::vector<gccjit::rvalue> elements) const 12996 12997Given a vector type, and a vector of scalar rvalue elements, generate a 12998vector rvalue. 12999 13000The number of elements needs to match that of the vector type. 13001@end deffn 13002 13003@node Unary Operations<2>,Binary Operations<2>,Vector expressions<2>,Rvalues<2> 13004@anchor{cp/topics/expressions unary-operations}@anchor{220} 13005@subsubsection Unary Operations 13006 13007 13008@geindex gccjit;;context;;new_unary_op (C++ function) 13009@anchor{cp/topics/expressions _CPPv4N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{221}@anchor{cp/topics/expressions _CPPv3N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{222}@anchor{cp/topics/expressions _CPPv2N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{223}@anchor{cp/topics/expressions gccjit context new_unary_op__gcc_jit_unary_op gccjit type gccjit rvalue gccjit location}@anchor{224} 13010@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc) 13011 13012Build a unary operation out of an input rvalue. 13013 13014Parameter @code{loc} is optional. 13015 13016This is a thin wrapper around the C API’s 13017@ref{a2,,gcc_jit_context_new_unary_op()} and the available unary 13018operations are documented there. 13019@end deffn 13020 13021There are shorter ways to spell the various specific kinds of unary 13022operation: 13023 13024@geindex gccjit;;context;;new_minus (C++ function) 13025@anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{225}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{226}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{227}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{228} 13026@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 13027 13028Negate an arithmetic value; for example: 13029 13030@example 13031gccjit::rvalue negpi = ctxt.new_minus (t_double, pi); 13032@end example 13033 13034builds the equivalent of this C expression: 13035 13036@example 13037-pi 13038@end example 13039@end deffn 13040 13041@geindex new_bitwise_negate (C++ function) 13042@anchor{cp/topics/expressions _CPPv418new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{229}@anchor{cp/topics/expressions _CPPv318new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22a}@anchor{cp/topics/expressions _CPPv218new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22b}@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{22c} 13043@deffn {C++ Function} gccjit::@ref{146,,rvalue} new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 13044 13045Bitwise negation of an integer value (one’s complement); for example: 13046 13047@example 13048gccjit::rvalue mask = ctxt.new_bitwise_negate (t_int, a); 13049@end example 13050 13051builds the equivalent of this C expression: 13052 13053@example 13054~a 13055@end example 13056@end deffn 13057 13058@geindex new_logical_negate (C++ function) 13059@anchor{cp/topics/expressions _CPPv418new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22d}@anchor{cp/topics/expressions _CPPv318new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22e}@anchor{cp/topics/expressions _CPPv218new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22f}@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{230} 13060@deffn {C++ Function} gccjit::@ref{146,,rvalue} new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) 13061 13062Logical negation of an arithmetic or pointer value; for example: 13063 13064@example 13065gccjit::rvalue guard = ctxt.new_logical_negate (t_bool, cond); 13066@end example 13067 13068builds the equivalent of this C expression: 13069 13070@example 13071!cond 13072@end example 13073@end deffn 13074 13075The most concise way to spell them is with overloaded operators: 13076 13077@geindex operator- (C++ function) 13078@anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueE}@anchor{231}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueE}@anchor{232}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueE}@anchor{233}@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{234} 13079@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator@w{-} (gccjit::rvalue a) 13080 13081@example 13082gccjit::rvalue negpi = -pi; 13083@end example 13084@end deffn 13085 13086@geindex operator~ (C++ function) 13087@anchor{cp/topics/expressions _CPPv4coN6gccjit6rvalueE}@anchor{235}@anchor{cp/topics/expressions _CPPv3coN6gccjit6rvalueE}@anchor{236}@anchor{cp/topics/expressions _CPPv2coN6gccjit6rvalueE}@anchor{237}@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{238} 13088@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator~ (gccjit::rvalue a) 13089 13090@example 13091gccjit::rvalue mask = ~a; 13092@end example 13093@end deffn 13094 13095@geindex operator! (C++ function) 13096@anchor{cp/topics/expressions _CPPv4ntN6gccjit6rvalueE}@anchor{239}@anchor{cp/topics/expressions _CPPv3ntN6gccjit6rvalueE}@anchor{23a}@anchor{cp/topics/expressions _CPPv2ntN6gccjit6rvalueE}@anchor{23b}@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{23c} 13097@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator! (gccjit::rvalue a) 13098 13099@example 13100gccjit::rvalue guard = !cond; 13101@end example 13102@end deffn 13103 13104@node Binary Operations<2>,Comparisons<2>,Unary Operations<2>,Rvalues<2> 13105@anchor{cp/topics/expressions binary-operations}@anchor{23d} 13106@subsubsection Binary Operations 13107 13108 13109@geindex gccjit;;context;;new_binary_op (C++ function) 13110@anchor{cp/topics/expressions _CPPv4N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{145}@anchor{cp/topics/expressions _CPPv3N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{23e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{23f}@anchor{cp/topics/expressions gccjit context new_binary_op__gcc_jit_binary_op gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{240} 13111@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13112 13113Build a binary operation out of two constituent rvalues. 13114 13115Parameter @code{loc} is optional. 13116 13117This is a thin wrapper around the C API’s 13118@ref{12,,gcc_jit_context_new_binary_op()} and the available binary 13119operations are documented there. 13120@end deffn 13121 13122There are shorter ways to spell the various specific kinds of binary 13123operation: 13124 13125@geindex gccjit;;context;;new_plus (C++ function) 13126@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{241}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{242}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{243}@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{244} 13127@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13128@end deffn 13129 13130@geindex gccjit;;context;;new_minus (C++ function) 13131@anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{245}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{246}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{247}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{248} 13132@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13133@end deffn 13134 13135@geindex gccjit;;context;;new_mult (C++ function) 13136@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{249}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24b}@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{24c} 13137@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13138@end deffn 13139 13140@geindex gccjit;;context;;new_divide (C++ function) 13141@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24f}@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{250} 13142@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13143@end deffn 13144 13145@geindex gccjit;;context;;new_modulo (C++ function) 13146@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{251}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{252}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{253}@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{254} 13147@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13148@end deffn 13149 13150@geindex gccjit;;context;;new_bitwise_and (C++ function) 13151@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{255}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{256}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{257}@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{258} 13152@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13153@end deffn 13154 13155@geindex gccjit;;context;;new_bitwise_xor (C++ function) 13156@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{259}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25b}@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{25c} 13157@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13158@end deffn 13159 13160@geindex gccjit;;context;;new_bitwise_or (C++ function) 13161@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25f}@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{260} 13162@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13163@end deffn 13164 13165@geindex gccjit;;context;;new_logical_and (C++ function) 13166@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{261}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{262}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{263}@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{264} 13167@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13168@end deffn 13169 13170@geindex gccjit;;context;;new_logical_or (C++ function) 13171@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{265}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{266}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{267}@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{268} 13172@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13173@end deffn 13174 13175The most concise way to spell them is with overloaded operators: 13176 13177@geindex operator+ (C++ function) 13178@anchor{cp/topics/expressions _CPPv4plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{269}@anchor{cp/topics/expressions _CPPv3plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26a}@anchor{cp/topics/expressions _CPPv2plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26b}@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{26c} 13179@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator+ (gccjit::rvalue a, gccjit::rvalue b) 13180 13181@example 13182gccjit::rvalue sum = a + b; 13183@end example 13184@end deffn 13185 13186@geindex operator- (C++ function) 13187@anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26d}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26e}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26f}@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{270} 13188@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator@w{-} (gccjit::rvalue a, gccjit::rvalue b) 13189 13190@example 13191gccjit::rvalue diff = a - b; 13192@end example 13193@end deffn 13194 13195@geindex operator* (C++ function) 13196@anchor{cp/topics/expressions _CPPv4mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{271}@anchor{cp/topics/expressions _CPPv3mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{272}@anchor{cp/topics/expressions _CPPv2mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{273}@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{274} 13197@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator* (gccjit::rvalue a, gccjit::rvalue b) 13198 13199@example 13200gccjit::rvalue prod = a * b; 13201@end example 13202@end deffn 13203 13204@geindex operator/ (C++ function) 13205@anchor{cp/topics/expressions _CPPv4dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{275}@anchor{cp/topics/expressions _CPPv3dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{276}@anchor{cp/topics/expressions _CPPv2dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{277}@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{278} 13206@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator/ (gccjit::rvalue a, gccjit::rvalue b) 13207 13208@example 13209gccjit::rvalue result = a / b; 13210@end example 13211@end deffn 13212 13213@geindex operator% (C++ function) 13214@anchor{cp/topics/expressions _CPPv4rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{279}@anchor{cp/topics/expressions _CPPv3rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27a}@anchor{cp/topics/expressions _CPPv2rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27b}@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{27c} 13215@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator% (gccjit::rvalue a, gccjit::rvalue b) 13216 13217@example 13218gccjit::rvalue mod = a % b; 13219@end example 13220@end deffn 13221 13222@geindex operator& (C++ function) 13223@anchor{cp/topics/expressions _CPPv4anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27d}@anchor{cp/topics/expressions _CPPv3anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27e}@anchor{cp/topics/expressions _CPPv2anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27f}@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{280} 13224@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator& (gccjit::rvalue a, gccjit::rvalue b) 13225 13226@example 13227gccjit::rvalue x = a & b; 13228@end example 13229@end deffn 13230 13231@geindex operator^ (C++ function) 13232@anchor{cp/topics/expressions _CPPv4eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{281}@anchor{cp/topics/expressions _CPPv3eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{282}@anchor{cp/topics/expressions _CPPv2eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{283}@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{284} 13233@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator^ (gccjit::rvalue a, gccjit::rvalue b) 13234 13235@example 13236gccjit::rvalue x = a ^ b; 13237@end example 13238@end deffn 13239 13240@geindex operator| (C++ function) 13241@anchor{cp/topics/expressions _CPPv4orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{285}@anchor{cp/topics/expressions _CPPv3orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{286}@anchor{cp/topics/expressions _CPPv2orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{287}@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{288} 13242@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator| (gccjit::rvalue a, gccjit::rvalue b) 13243 13244@example 13245gccjit::rvalue x = a | b; 13246@end example 13247@end deffn 13248 13249@geindex operator&& (C++ function) 13250@anchor{cp/topics/expressions _CPPv4aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{289}@anchor{cp/topics/expressions _CPPv3aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28a}@anchor{cp/topics/expressions _CPPv2aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28b}@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{28c} 13251@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator&& (gccjit::rvalue a, gccjit::rvalue b) 13252 13253@example 13254gccjit::rvalue cond = a && b; 13255@end example 13256@end deffn 13257 13258@geindex operator|| (C++ function) 13259@anchor{cp/topics/expressions _CPPv4ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28d}@anchor{cp/topics/expressions _CPPv3ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28e}@anchor{cp/topics/expressions _CPPv2ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28f}@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{290} 13260@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator|| (gccjit::rvalue a, gccjit::rvalue b) 13261 13262@example 13263gccjit::rvalue cond = a || b; 13264@end example 13265@end deffn 13266 13267These can of course be combined, giving a terse way to build compound 13268expressions: 13269 13270@quotation 13271 13272@example 13273gccjit::rvalue discriminant = (b * b) - (four * a * c); 13274@end example 13275@end quotation 13276 13277@node Comparisons<2>,Function calls<2>,Binary Operations<2>,Rvalues<2> 13278@anchor{cp/topics/expressions comparisons}@anchor{291} 13279@subsubsection Comparisons 13280 13281 13282@geindex gccjit;;context;;new_comparison (C++ function) 13283@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{157}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{292}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{293}@anchor{cp/topics/expressions gccjit context new_comparison__gcc_jit_comparison gccjit rvalue gccjit rvalue gccjit location}@anchor{294} 13284@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13285 13286Build a boolean rvalue out of the comparison of two other rvalues. 13287 13288Parameter @code{loc} is optional. 13289 13290This is a thin wrapper around the C API’s 13291@ref{2c,,gcc_jit_context_new_comparison()} and the available kinds 13292of comparison are documented there. 13293@end deffn 13294 13295There are shorter ways to spell the various specific kinds of binary 13296operation: 13297 13298@geindex gccjit;;context;;new_eq (C++ function) 13299@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{295}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{296}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{297}@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{298} 13300@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13301@end deffn 13302 13303@geindex gccjit;;context;;new_ne (C++ function) 13304@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{299}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29b}@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{29c} 13305@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13306@end deffn 13307 13308@geindex gccjit;;context;;new_lt (C++ function) 13309@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29f}@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a0} 13310@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13311@end deffn 13312 13313@geindex gccjit;;context;;new_le (C++ function) 13314@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a3}@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a4} 13315@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13316@end deffn 13317 13318@geindex gccjit;;context;;new_gt (C++ function) 13319@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a5}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a6}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a7}@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a8} 13320@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13321@end deffn 13322 13323@geindex gccjit;;context;;new_ge (C++ function) 13324@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a9}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2aa}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ab}@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{2ac} 13325@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) 13326@end deffn 13327 13328The most concise way to spell them is with overloaded operators: 13329 13330@geindex operator== (C++ function) 13331@anchor{cp/topics/expressions _CPPv4eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ad}@anchor{cp/topics/expressions _CPPv3eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ae}@anchor{cp/topics/expressions _CPPv2eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2af}@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{2b0} 13332@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator== (gccjit::rvalue a, gccjit::rvalue b) 13333 13334@example 13335gccjit::rvalue cond = (a == ctxt.zero (t_int)); 13336@end example 13337@end deffn 13338 13339@geindex operator!= (C++ function) 13340@anchor{cp/topics/expressions _CPPv4neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b1}@anchor{cp/topics/expressions _CPPv3neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b2}@anchor{cp/topics/expressions _CPPv2neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b3}@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{2b4} 13341@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator!= (gccjit::rvalue a, gccjit::rvalue b) 13342 13343@example 13344gccjit::rvalue cond = (i != j); 13345@end example 13346@end deffn 13347 13348@geindex operator< (C++ function) 13349@anchor{cp/topics/expressions _CPPv4ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b5}@anchor{cp/topics/expressions _CPPv3ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b6}@anchor{cp/topics/expressions _CPPv2ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b7}@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{2b8} 13350@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator< (gccjit::rvalue a, gccjit::rvalue b) 13351 13352@example 13353gccjit::rvalue cond = i < n; 13354@end example 13355@end deffn 13356 13357@geindex operator<= (C++ function) 13358@anchor{cp/topics/expressions _CPPv4leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b9}@anchor{cp/topics/expressions _CPPv3leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ba}@anchor{cp/topics/expressions _CPPv2leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bb}@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{2bc} 13359@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator<= (gccjit::rvalue a, gccjit::rvalue b) 13360 13361@example 13362gccjit::rvalue cond = i <= n; 13363@end example 13364@end deffn 13365 13366@geindex operator> (C++ function) 13367@anchor{cp/topics/expressions _CPPv4gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bd}@anchor{cp/topics/expressions _CPPv3gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2be}@anchor{cp/topics/expressions _CPPv2gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bf}@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{2c0} 13368@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator> (gccjit::rvalue a, gccjit::rvalue b) 13369 13370@example 13371gccjit::rvalue cond = (ch > limit); 13372@end example 13373@end deffn 13374 13375@geindex operator>= (C++ function) 13376@anchor{cp/topics/expressions _CPPv4geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c1}@anchor{cp/topics/expressions _CPPv3geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c2}@anchor{cp/topics/expressions _CPPv2geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c3}@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{2c4} 13377@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator>= (gccjit::rvalue a, gccjit::rvalue b) 13378 13379@example 13380gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100)); 13381@end example 13382@end deffn 13383 13384@c TODO: beyond this point 13385 13386@node Function calls<2>,Function pointers<3>,Comparisons<2>,Rvalues<2> 13387@anchor{cp/topics/expressions function-calls}@anchor{2c5} 13388@subsubsection Function calls 13389 13390 13391@geindex gcc_jit_context_new_call (C++ function) 13392@anchor{cp/topics/expressions _CPPv424gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c6}@anchor{cp/topics/expressions _CPPv324gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c7}@anchor{cp/topics/expressions _CPPv224gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c8}@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{2c9} 13393@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) 13394 13395Given a function and the given table of argument rvalues, construct a 13396call to the function, with the result as an rvalue. 13397 13398@cartouche 13399@quotation Note 13400@code{gccjit::context::new_call()} merely builds a 13401@ref{146,,gccjit;;rvalue} i.e. an expression that can be evaluated, 13402perhaps as part of a more complicated expression. 13403The call @emph{won’t} happen unless you add a statement to a function 13404that evaluates the expression. 13405 13406For example, if you want to call a function and discard the result 13407(or to call a function with @code{void} return type), use 13408@ref{2ca,,gccjit;;block;;add_eval()}: 13409 13410@example 13411/* Add "(void)printf (arg0, arg1);". */ 13412block.add_eval (ctxt.new_call (printf_func, arg0, arg1)); 13413@end example 13414@end quotation 13415@end cartouche 13416@end deffn 13417 13418@node Function pointers<3>,Type-coercion<2>,Function calls<2>,Rvalues<2> 13419@anchor{cp/topics/expressions function-pointers}@anchor{2cb} 13420@subsubsection Function pointers 13421 13422 13423@geindex gccjit;;function;;get_address (C++ function) 13424@anchor{cp/topics/expressions _CPPv4N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2cc}@anchor{cp/topics/expressions _CPPv3N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2cd}@anchor{cp/topics/expressions _CPPv2N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2ce}@anchor{cp/topics/expressions gccjit function get_address__gccjit location}@anchor{2cf} 13425@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{154,,function}::get_address (gccjit::location loc) 13426 13427Get the address of a function as an rvalue, of function pointer 13428type. 13429@end deffn 13430 13431@node Type-coercion<2>,,Function pointers<3>,Rvalues<2> 13432@anchor{cp/topics/expressions type-coercion}@anchor{2d0} 13433@subsubsection Type-coercion 13434 13435 13436@geindex gccjit;;context;;new_cast (C++ function) 13437@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d3}@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{2d4} 13438@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc) 13439 13440Given an rvalue of T, construct another rvalue of another type. 13441 13442Currently only a limited set of conversions are possible: 13443 13444@quotation 13445 13446 13447@itemize * 13448 13449@item 13450int <-> float 13451 13452@item 13453int <-> bool 13454 13455@item 13456P* <-> Q*, for pointer types P and Q 13457@end itemize 13458@end quotation 13459@end deffn 13460 13461@node Lvalues<2>,Working with pointers structs and unions<2>,Rvalues<2>,Expressions<2> 13462@anchor{cp/topics/expressions lvalues}@anchor{2d5} 13463@subsubsection Lvalues 13464 13465 13466@geindex gccjit;;lvalue (C++ class) 13467@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalueE}@anchor{14f}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalueE}@anchor{2d6}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalueE}@anchor{2d7}@anchor{cp/topics/expressions gccjit lvalue}@anchor{2d8} 13468@deffn {C++ Class} gccjit::lvalue 13469@end deffn 13470 13471An lvalue is something that can of the @emph{left}-hand side of an assignment: 13472a storage area (such as a variable). It is a subclass of 13473@ref{146,,gccjit;;rvalue}, where the rvalue is computed by reading from the 13474storage area. 13475 13476It iss a thin wrapper around @ref{24,,gcc_jit_lvalue *} from the C API. 13477 13478@geindex gccjit;;lvalue;;get_address (C++ function) 13479@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2d9}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2da}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2db}@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{2dc} 13480@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{14f,,lvalue}::get_address (gccjit::location loc) 13481 13482Take the address of an lvalue; analogous to: 13483 13484@example 13485&(EXPR) 13486@end example 13487 13488in C. 13489 13490Parameter “loc” is optional. 13491@end deffn 13492 13493@menu 13494* Global variables: Global variables<2>. 13495 13496@end menu 13497 13498@node Global variables<2>,,,Lvalues<2> 13499@anchor{cp/topics/expressions global-variables}@anchor{2dd} 13500@subsubsection Global variables 13501 13502 13503@geindex gccjit;;context;;new_global (C++ function) 13504@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2de}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2df}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2e0}@anchor{cp/topics/expressions gccjit context new_global__gcc_jit_global_kind gccjit type cCP gccjit location}@anchor{2e1} 13505@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{13d,,context}::new_global (enum gcc_jit_global_kind, gccjit::type type, const char *name, gccjit::location loc) 13506 13507Add a new global variable of the given type and name to the context. 13508 13509This is a thin wrapper around @ref{c8,,gcc_jit_context_new_global()} from 13510the C API; the “kind” parameter has the same meaning as there. 13511@end deffn 13512 13513@node Working with pointers structs and unions<2>,,Lvalues<2>,Expressions<2> 13514@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{2e2} 13515@subsubsection Working with pointers, structs and unions 13516 13517 13518@geindex gccjit;;rvalue;;dereference (C++ function) 13519@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e3}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e4}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e5}@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{2e6} 13520@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::dereference (gccjit::location loc) 13521 13522Given an rvalue of pointer type @code{T *}, dereferencing the pointer, 13523getting an lvalue of type @code{T}. Analogous to: 13524 13525@example 13526*(EXPR) 13527@end example 13528 13529in C. 13530 13531Parameter “loc” is optional. 13532@end deffn 13533 13534If you don’t need to specify the location, this can also be expressed using 13535an overloaded operator: 13536 13537@geindex gccjit;;rvalue;;operator* (C++ function) 13538@anchor{cp/topics/expressions _CPPv4N6gccjit6rvaluemlEv}@anchor{2e7}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvaluemlEv}@anchor{2e8}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvaluemlEv}@anchor{2e9}@anchor{cp/topics/expressions gccjit rvalue mul-operator}@anchor{2ea} 13539@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::operator* () 13540 13541@example 13542gccjit::lvalue content = *ptr; 13543@end example 13544@end deffn 13545 13546Field access is provided separately for both lvalues and rvalues: 13547 13548@geindex gccjit;;lvalue;;access_field (C++ function) 13549@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2eb}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ec}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ed}@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{2ee} 13550@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{14f,,lvalue}::access_field (gccjit::field field, gccjit::location loc) 13551 13552Given an lvalue of struct or union type, access the given field, 13553getting an lvalue of the field’s type. Analogous to: 13554 13555@example 13556(EXPR).field = ...; 13557@end example 13558 13559in C. 13560@end deffn 13561 13562@geindex gccjit;;rvalue;;access_field (C++ function) 13563@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ef}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f0}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f1}@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{2f2} 13564@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{146,,rvalue}::access_field (gccjit::field field, gccjit::location loc) 13565 13566Given an rvalue of struct or union type, access the given field 13567as an rvalue. Analogous to: 13568 13569@example 13570(EXPR).field 13571@end example 13572 13573in C. 13574@end deffn 13575 13576@geindex gccjit;;rvalue;;dereference_field (C++ function) 13577@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f3}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f4}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f5}@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{2f6} 13578@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::dereference_field (gccjit::field field, gccjit::location loc) 13579 13580Given an rvalue of pointer type @code{T *} where T is of struct or union 13581type, access the given field as an lvalue. Analogous to: 13582 13583@example 13584(EXPR)->field 13585@end example 13586 13587in C, itself equivalent to @code{(*EXPR).FIELD}. 13588@end deffn 13589 13590@geindex gccjit;;context;;new_array_access (C++ function) 13591@anchor{cp/topics/expressions _CPPv4N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f7}@anchor{cp/topics/expressions _CPPv3N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f8}@anchor{cp/topics/expressions _CPPv2N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f9}@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{2fa} 13592@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{13d,,context}::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc) 13593 13594Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at 13595the given index, using standard C array indexing rules i.e. each 13596increment of @code{index} corresponds to @code{sizeof(T)} bytes. 13597Analogous to: 13598 13599@example 13600PTR[INDEX] 13601@end example 13602 13603in C (or, indeed, to @code{PTR + INDEX}). 13604 13605Parameter “loc” is optional. 13606@end deffn 13607 13608For array accesses where you don’t need to specify a @ref{163,,gccjit;;location}, 13609two overloaded operators are available: 13610 13611@quotation 13612 13613gccjit::lvalue gccjit::rvalue::operator[] (gccjit::rvalue index) 13614 13615@example 13616gccjit::lvalue element = array[idx]; 13617@end example 13618 13619gccjit::lvalue gccjit::rvalue::operator[] (int index) 13620 13621@example 13622gccjit::lvalue element = array[0]; 13623@end example 13624@end quotation 13625 13626@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 13627@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 13628@c 13629@c This is free software: you can redistribute it and/or modify it 13630@c under the terms of the GNU General Public License as published by 13631@c the Free Software Foundation, either version 3 of the License, or 13632@c (at your option) any later version. 13633@c 13634@c This program is distributed in the hope that it will be useful, but 13635@c WITHOUT ANY WARRANTY; without even the implied warranty of 13636@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13637@c General Public License for more details. 13638@c 13639@c You should have received a copy of the GNU General Public License 13640@c along with this program. If not, see 13641@c <http://www.gnu.org/licenses/>. 13642 13643@node Creating and using functions<2>,Source Locations<2>,Expressions<2>,Topic Reference<2> 13644@anchor{cp/topics/functions doc}@anchor{2fb}@anchor{cp/topics/functions creating-and-using-functions}@anchor{2fc} 13645@subsection Creating and using functions 13646 13647 13648@menu 13649* Params: Params<2>. 13650* Functions: Functions<2>. 13651* Blocks: Blocks<2>. 13652* Statements: Statements<2>. 13653 13654@end menu 13655 13656@node Params<2>,Functions<2>,,Creating and using functions<2> 13657@anchor{cp/topics/functions params}@anchor{2fd} 13658@subsubsection Params 13659 13660 13661@geindex gccjit;;param (C++ class) 13662@anchor{cp/topics/functions _CPPv4N6gccjit5paramE}@anchor{150}@anchor{cp/topics/functions _CPPv3N6gccjit5paramE}@anchor{2fe}@anchor{cp/topics/functions _CPPv2N6gccjit5paramE}@anchor{2ff}@anchor{cp/topics/functions gccjit param}@anchor{300} 13663@deffn {C++ Class} gccjit::param 13664 13665A @cite{gccjit::param} represents a parameter to a function. 13666@end deffn 13667 13668@geindex gccjit;;context;;new_param (C++ function) 13669@anchor{cp/topics/functions _CPPv4N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{144}@anchor{cp/topics/functions _CPPv3N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{301}@anchor{cp/topics/functions _CPPv2N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{302}@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{303} 13670@deffn {C++ Function} gccjit::@ref{150,,param} gccjit::@ref{13d,,context}::new_param (gccjit::type type, const char *name, gccjit::location loc) 13671 13672In preparation for creating a function, create a new parameter of the 13673given type and name. 13674@end deffn 13675 13676@ref{150,,gccjit;;param} is a subclass of @ref{14f,,gccjit;;lvalue} (and thus 13677of @ref{146,,gccjit;;rvalue} and @ref{142,,gccjit;;object}). It is a thin 13678wrapper around the C API’s @ref{25,,gcc_jit_param *}. 13679 13680@node Functions<2>,Blocks<2>,Params<2>,Creating and using functions<2> 13681@anchor{cp/topics/functions functions}@anchor{304} 13682@subsubsection Functions 13683 13684 13685@geindex gccjit;;function (C++ class) 13686@anchor{cp/topics/functions _CPPv4N6gccjit8functionE}@anchor{154}@anchor{cp/topics/functions _CPPv3N6gccjit8functionE}@anchor{305}@anchor{cp/topics/functions _CPPv2N6gccjit8functionE}@anchor{306}@anchor{cp/topics/functions gccjit function}@anchor{307} 13687@deffn {C++ Class} gccjit::function 13688 13689A @cite{gccjit::function} represents a function - either one that we’re 13690creating ourselves, or one that we’re referencing. 13691@end deffn 13692 13693@geindex gccjit;;context;;new_function (C++ function) 13694@anchor{cp/topics/functions _CPPv4N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{308}@anchor{cp/topics/functions _CPPv3N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{309}@anchor{cp/topics/functions _CPPv2N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{30a}@anchor{cp/topics/functions gccjit context new_function__gcc_jit_function_kind gccjit type cCP std vector param R i gccjit location}@anchor{30b} 13695@deffn {C++ Function} gccjit::@ref{154,,function} gccjit::@ref{13d,,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) 13696 13697Create a gcc_jit_function with the given name and parameters. 13698 13699Parameters “is_variadic” and “loc” are optional. 13700 13701This is a wrapper around the C API’s @ref{11,,gcc_jit_context_new_function()}. 13702@end deffn 13703 13704@geindex gccjit;;context;;get_builtin_function (C++ function) 13705@anchor{cp/topics/functions _CPPv4N6gccjit7context20get_builtin_functionEPKc}@anchor{30c}@anchor{cp/topics/functions _CPPv3N6gccjit7context20get_builtin_functionEPKc}@anchor{30d}@anchor{cp/topics/functions _CPPv2N6gccjit7context20get_builtin_functionEPKc}@anchor{30e}@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{30f} 13706@deffn {C++ Function} gccjit::@ref{154,,function} gccjit::@ref{13d,,context}::get_builtin_function (const char *name) 13707 13708This is a wrapper around the C API’s 13709@ref{e1,,gcc_jit_context_get_builtin_function()}. 13710@end deffn 13711 13712@geindex gccjit;;function;;get_param (C++ function) 13713@anchor{cp/topics/functions _CPPv4NK6gccjit8function9get_paramEi}@anchor{310}@anchor{cp/topics/functions _CPPv3NK6gccjit8function9get_paramEi}@anchor{311}@anchor{cp/topics/functions _CPPv2NK6gccjit8function9get_paramEi}@anchor{312}@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{313} 13714@deffn {C++ Function} gccjit::@ref{150,,param} gccjit::@ref{154,,function}::get_param (int index) const 13715 13716Get the param of the given index (0-based). 13717@end deffn 13718 13719@geindex gccjit;;function;;dump_to_dot (C++ function) 13720@anchor{cp/topics/functions _CPPv4N6gccjit8function11dump_to_dotEPKc}@anchor{15c}@anchor{cp/topics/functions _CPPv3N6gccjit8function11dump_to_dotEPKc}@anchor{314}@anchor{cp/topics/functions _CPPv2N6gccjit8function11dump_to_dotEPKc}@anchor{315}@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{316} 13721@deffn {C++ Function} void gccjit::@ref{154,,function}::dump_to_dot (const char *path) 13722 13723Emit the function in graphviz format to the given path. 13724@end deffn 13725 13726@geindex gccjit;;function;;new_local (C++ function) 13727@anchor{cp/topics/functions _CPPv4N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{151}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{317}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{318}@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{319} 13728@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{154,,function}::new_local (gccjit::type type, const char *name, gccjit::location loc) 13729 13730Create a new local variable within the function, of the given type and 13731name. 13732@end deffn 13733 13734@node Blocks<2>,Statements<2>,Functions<2>,Creating and using functions<2> 13735@anchor{cp/topics/functions blocks}@anchor{31a} 13736@subsubsection Blocks 13737 13738 13739@geindex gccjit;;block (C++ class) 13740@anchor{cp/topics/functions _CPPv4N6gccjit5blockE}@anchor{153}@anchor{cp/topics/functions _CPPv3N6gccjit5blockE}@anchor{31b}@anchor{cp/topics/functions _CPPv2N6gccjit5blockE}@anchor{31c}@anchor{cp/topics/functions gccjit block}@anchor{31d} 13741@deffn {C++ Class} gccjit::block 13742 13743A @cite{gccjit::block} represents a basic block within a function i.e. a 13744sequence of statements with a single entry point and a single exit 13745point. 13746 13747@ref{153,,gccjit;;block} is a subclass of @ref{142,,gccjit;;object}. 13748 13749The first basic block that you create within a function will 13750be the entrypoint. 13751 13752Each basic block that you create within a function must be 13753terminated, either with a conditional, a jump, a return, or 13754a switch. 13755 13756It’s legal to have multiple basic blocks that return within 13757one function. 13758@end deffn 13759 13760@geindex gccjit;;function;;new_block (C++ function) 13761@anchor{cp/topics/functions _CPPv4N6gccjit8function9new_blockEPKc}@anchor{31e}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_blockEPKc}@anchor{31f}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_blockEPKc}@anchor{320}@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{321} 13762@deffn {C++ Function} gccjit::@ref{153,,block} gccjit::@ref{154,,function}::new_block (const char *name) 13763 13764Create a basic block of the given name. The name may be NULL, but 13765providing meaningful names is often helpful when debugging: it may 13766show up in dumps of the internal representation, and in error 13767messages. 13768@end deffn 13769 13770@node Statements<2>,,Blocks<2>,Creating and using functions<2> 13771@anchor{cp/topics/functions statements}@anchor{322} 13772@subsubsection Statements 13773 13774 13775@geindex gccjit;;block;;add_eval (C++ function) 13776@anchor{cp/topics/functions _CPPv4N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ca}@anchor{cp/topics/functions _CPPv3N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{323}@anchor{cp/topics/functions _CPPv2N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{324}@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{325} 13777@deffn {C++ Function} void gccjit::@ref{153,,block}::add_eval (gccjit::rvalue rvalue, gccjit::location loc) 13778 13779Add evaluation of an rvalue, discarding the result 13780(e.g. a function call that “returns” void). 13781 13782This is equivalent to this C code: 13783 13784@example 13785(void)expression; 13786@end example 13787@end deffn 13788 13789@geindex gccjit;;block;;add_assignment (C++ function) 13790@anchor{cp/topics/functions _CPPv4N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{155}@anchor{cp/topics/functions _CPPv3N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{326}@anchor{cp/topics/functions _CPPv2N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{327}@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{328} 13791@deffn {C++ Function} void gccjit::@ref{153,,block}::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc) 13792 13793Add evaluation of an rvalue, assigning the result to the given 13794lvalue. 13795 13796This is roughly equivalent to this C code: 13797 13798@example 13799lvalue = rvalue; 13800@end example 13801@end deffn 13802 13803@geindex gccjit;;block;;add_assignment_op (C++ function) 13804@anchor{cp/topics/functions _CPPv4N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{159}@anchor{cp/topics/functions _CPPv3N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{329}@anchor{cp/topics/functions _CPPv2N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{32a}@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue gcc_jit_binary_op gccjit rvalue gccjit location}@anchor{32b} 13805@deffn {C++ Function} void gccjit::@ref{153,,block}::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc) 13806 13807Add evaluation of an rvalue, using the result to modify an 13808lvalue. 13809 13810This is analogous to “+=” and friends: 13811 13812@example 13813lvalue += rvalue; 13814lvalue *= rvalue; 13815lvalue /= rvalue; 13816@end example 13817 13818etc. For example: 13819 13820@example 13821/* "i++" */ 13822loop_body.add_assignment_op ( 13823 i, 13824 GCC_JIT_BINARY_OP_PLUS, 13825 ctxt.one (int_type)); 13826@end example 13827@end deffn 13828 13829@geindex gccjit;;block;;add_comment (C++ function) 13830@anchor{cp/topics/functions _CPPv4N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{165}@anchor{cp/topics/functions _CPPv3N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{32c}@anchor{cp/topics/functions _CPPv2N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{32d}@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{32e} 13831@deffn {C++ Function} void gccjit::@ref{153,,block}::add_comment (const char *text, gccjit::location loc) 13832 13833Add a no-op textual comment to the internal representation of the 13834code. It will be optimized away, but will be visible in the dumps 13835seen via @ref{66,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} 13836and @ref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, 13837and thus may be of use when debugging how your project’s internal 13838representation gets converted to the libgccjit IR. 13839 13840Parameter “loc” is optional. 13841@end deffn 13842 13843@geindex gccjit;;block;;end_with_conditional (C++ function) 13844@anchor{cp/topics/functions _CPPv4N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{158}@anchor{cp/topics/functions _CPPv3N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{32f}@anchor{cp/topics/functions _CPPv2N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{330}@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{331} 13845@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc) 13846 13847Terminate a block by adding evaluation of an rvalue, branching on the 13848result to the appropriate successor block. 13849 13850This is roughly equivalent to this C code: 13851 13852@example 13853if (boolval) 13854 goto on_true; 13855else 13856 goto on_false; 13857@end example 13858 13859block, boolval, on_true, and on_false must be non-NULL. 13860@end deffn 13861 13862@geindex gccjit;;block;;end_with_jump (C++ function) 13863@anchor{cp/topics/functions _CPPv4N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{332}@anchor{cp/topics/functions _CPPv3N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{333}@anchor{cp/topics/functions _CPPv2N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{334}@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{335} 13864@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_jump (gccjit::block target, gccjit::location loc) 13865 13866Terminate a block by adding a jump to the given target block. 13867 13868This is roughly equivalent to this C code: 13869 13870@example 13871goto target; 13872@end example 13873@end deffn 13874 13875@geindex gccjit;;block;;end_with_return (C++ function) 13876@anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{336}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{337}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{338}@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{339} 13877@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_return (gccjit::rvalue rvalue, gccjit::location loc) 13878 13879Terminate a block. 13880 13881Both params are optional. 13882 13883An rvalue must be provided for a function returning non-void, and 13884must not be provided by a function “returning” @cite{void}. 13885 13886If an rvalue is provided, the block is terminated by evaluating the 13887rvalue and returning the value. 13888 13889This is roughly equivalent to this C code: 13890 13891@example 13892return expression; 13893@end example 13894 13895If an rvalue is not provided, the block is terminated by adding a 13896valueless return, for use within a function with “void” return type. 13897 13898This is equivalent to this C code: 13899 13900@example 13901return; 13902@end example 13903@end deffn 13904 13905@geindex gccjit;;block;;end_with_switch (C++ function) 13906@anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33a}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33b}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33c}@anchor{cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location}@anchor{33d} 13907@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_switch (gccjit::rvalue expr, gccjit::block default_block, std::vector<gccjit::case_> cases, gccjit::location loc) 13908 13909Terminate a block by adding evalation of an rvalue, then performing 13910a multiway branch. 13911 13912This is roughly equivalent to this C code: 13913 13914@example 13915switch (expr) 13916 @{ 13917 default: 13918 goto default_block; 13919 13920 case C0.min_value ... C0.max_value: 13921 goto C0.dest_block; 13922 13923 case C1.min_value ... C1.max_value: 13924 goto C1.dest_block; 13925 13926 ...etc... 13927 13928 case C[N - 1].min_value ... C[N - 1].max_value: 13929 goto C[N - 1].dest_block; 13930@} 13931@end example 13932 13933@code{expr} must be of the same integer type as all of the @code{min_value} 13934and @code{max_value} within the cases. 13935 13936The ranges of the cases must not overlap (or have duplicate 13937values). 13938 13939The API entrypoints relating to switch statements and cases: 13940 13941@quotation 13942 13943 13944@itemize * 13945 13946@item 13947@ref{33a,,gccjit;;block;;end_with_switch()} 13948 13949@item 13950@code{gccjit::context::new_case()} 13951@end itemize 13952@end quotation 13953 13954were added in @ref{ef,,LIBGCCJIT_ABI_3}; you can test for their presence 13955using 13956 13957@example 13958#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS 13959@end example 13960 13961A @cite{gccjit::case_} represents a case within a switch statement, and 13962is created within a particular @ref{13d,,gccjit;;context} using 13963@code{gccjit::context::new_case()}. It is a subclass of 13964@ref{142,,gccjit;;object}. 13965 13966Each case expresses a multivalued range of integer values. You 13967can express single-valued cases by passing in the same value for 13968both @cite{min_value} and @cite{max_value}. 13969 13970Here’s an example of creating a switch statement: 13971 13972@quotation 13973 13974@example 13975 13976void 13977create_code (gcc_jit_context *c_ctxt, void *user_data) 13978@{ 13979 /* Let's try to inject the equivalent of: 13980 int 13981 test_switch (int x) 13982 @{ 13983 switch (x) 13984 @{ 13985 case 0 ... 5: 13986 return 3; 13987 13988 case 25 ... 27: 13989 return 4; 13990 13991 case -42 ... -17: 13992 return 83; 13993 13994 case 40: 13995 return 8; 13996 13997 default: 13998 return 10; 13999 @} 14000 @} 14001 */ 14002 gccjit::context ctxt (c_ctxt); 14003 gccjit::type t_int = ctxt.get_type (GCC_JIT_TYPE_INT); 14004 gccjit::type return_type = t_int; 14005 gccjit::param x = ctxt.new_param (t_int, "x"); 14006 std::vector <gccjit::param> params; 14007 params.push_back (x); 14008 gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, 14009 return_type, 14010 "test_switch", 14011 params, 0); 14012 14013 gccjit::block b_initial = func.new_block ("initial"); 14014 14015 gccjit::block b_default = func.new_block ("default"); 14016 gccjit::block b_case_0_5 = func.new_block ("case_0_5"); 14017 gccjit::block b_case_25_27 = func.new_block ("case_25_27"); 14018 gccjit::block b_case_m42_m17 = func.new_block ("case_m42_m17"); 14019 gccjit::block b_case_40 = func.new_block ("case_40"); 14020 14021 std::vector <gccjit::case_> cases; 14022 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 0), 14023 ctxt.new_rvalue (t_int, 5), 14024 b_case_0_5)); 14025 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 25), 14026 ctxt.new_rvalue (t_int, 27), 14027 b_case_25_27)); 14028 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, -42), 14029 ctxt.new_rvalue (t_int, -17), 14030 b_case_m42_m17)); 14031 cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 40), 14032 ctxt.new_rvalue (t_int, 40), 14033 b_case_40)); 14034 b_initial.end_with_switch (x, 14035 b_default, 14036 cases); 14037 14038 b_case_0_5.end_with_return (ctxt.new_rvalue (t_int, 3)); 14039 b_case_25_27.end_with_return (ctxt.new_rvalue (t_int, 4)); 14040 b_case_m42_m17.end_with_return (ctxt.new_rvalue (t_int, 83)); 14041 b_case_40.end_with_return (ctxt.new_rvalue (t_int, 8)); 14042 b_default.end_with_return (ctxt.new_rvalue (t_int, 10)); 14043@} 14044 14045@end example 14046@end quotation 14047@end deffn 14048 14049@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 14050@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 14051@c 14052@c This is free software: you can redistribute it and/or modify it 14053@c under the terms of the GNU General Public License as published by 14054@c the Free Software Foundation, either version 3 of the License, or 14055@c (at your option) any later version. 14056@c 14057@c This program is distributed in the hope that it will be useful, but 14058@c WITHOUT ANY WARRANTY; without even the implied warranty of 14059@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14060@c General Public License for more details. 14061@c 14062@c You should have received a copy of the GNU General Public License 14063@c along with this program. If not, see 14064@c <http://www.gnu.org/licenses/>. 14065 14066@node Source Locations<2>,Compiling a context<2>,Creating and using functions<2>,Topic Reference<2> 14067@anchor{cp/topics/locations doc}@anchor{33e}@anchor{cp/topics/locations source-locations}@anchor{33f} 14068@subsection Source Locations 14069 14070 14071@geindex gccjit;;location (C++ class) 14072@anchor{cp/topics/locations _CPPv4N6gccjit8locationE}@anchor{163}@anchor{cp/topics/locations _CPPv3N6gccjit8locationE}@anchor{340}@anchor{cp/topics/locations _CPPv2N6gccjit8locationE}@anchor{341}@anchor{cp/topics/locations gccjit location}@anchor{342} 14073@deffn {C++ Class} gccjit::location 14074 14075A @cite{gccjit::location} encapsulates a source code location, so that 14076you can (optionally) associate locations in your language with 14077statements in the JIT-compiled code, allowing the debugger to 14078single-step through your language. 14079 14080@cite{gccjit::location} instances are optional: you can always omit them 14081from any C++ API entrypoint accepting one. 14082 14083You can construct them using @ref{169,,gccjit;;context;;new_location()}. 14084 14085You need to enable @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the 14086@ref{13d,,gccjit;;context} for these locations to actually be usable by 14087the debugger: 14088 14089@example 14090ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); 14091@end example 14092@end deffn 14093 14094@geindex gccjit;;context;;new_location (C++ function) 14095@anchor{cp/topics/locations _CPPv4N6gccjit7context12new_locationEPKcii}@anchor{169}@anchor{cp/topics/locations _CPPv3N6gccjit7context12new_locationEPKcii}@anchor{343}@anchor{cp/topics/locations _CPPv2N6gccjit7context12new_locationEPKcii}@anchor{344}@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{345} 14096@deffn {C++ Function} gccjit::@ref{163,,location} gccjit::@ref{13d,,context}::new_location (const char *filename, int line, int column) 14097 14098Create a @cite{gccjit::location} instance representing the given source 14099location. 14100@end deffn 14101 14102@menu 14103* Faking it: Faking it<2>. 14104 14105@end menu 14106 14107@node Faking it<2>,,,Source Locations<2> 14108@anchor{cp/topics/locations faking-it}@anchor{346} 14109@subsubsection Faking it 14110 14111 14112If you don’t have source code for your internal representation, but need 14113to debug, you can generate a C-like representation of the functions in 14114your context using @ref{188,,gccjit;;context;;dump_to_file()}: 14115 14116@example 14117ctxt.dump_to_file ("/tmp/something.c", 14118 1 /* update_locations */); 14119@end example 14120 14121This will dump C-like code to the given path. If the @cite{update_locations} 14122argument is true, this will also set up @cite{gccjit::location} information 14123throughout the context, pointing at the dump file as if it were a source 14124file, giving you @emph{something} you can step through in the debugger. 14125 14126@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 14127@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 14128@c 14129@c This is free software: you can redistribute it and/or modify it 14130@c under the terms of the GNU General Public License as published by 14131@c the Free Software Foundation, either version 3 of the License, or 14132@c (at your option) any later version. 14133@c 14134@c This program is distributed in the hope that it will be useful, but 14135@c WITHOUT ANY WARRANTY; without even the implied warranty of 14136@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14137@c General Public License for more details. 14138@c 14139@c You should have received a copy of the GNU General Public License 14140@c along with this program. If not, see 14141@c <http://www.gnu.org/licenses/>. 14142 14143@node Compiling a context<2>,Using Assembly Language with libgccjit++,Source Locations<2>,Topic Reference<2> 14144@anchor{cp/topics/compilation doc}@anchor{347}@anchor{cp/topics/compilation compiling-a-context}@anchor{348} 14145@subsection Compiling a context 14146 14147 14148Once populated, a @ref{13d,,gccjit;;context} can be compiled to 14149machine code, either in-memory via @ref{147,,gccjit;;context;;compile()} or 14150to disk via @ref{349,,gccjit;;context;;compile_to_file()}. 14151 14152You can compile a context multiple times (using either form of 14153compilation), although any errors that occur on the context will 14154prevent any future compilation of that context. 14155 14156@menu 14157* In-memory compilation: In-memory compilation<2>. 14158* Ahead-of-time compilation: Ahead-of-time compilation<2>. 14159 14160@end menu 14161 14162@node In-memory compilation<2>,Ahead-of-time compilation<2>,,Compiling a context<2> 14163@anchor{cp/topics/compilation in-memory-compilation}@anchor{34a} 14164@subsubsection In-memory compilation 14165 14166 14167@geindex gccjit;;context;;compile (C++ function) 14168@anchor{cp/topics/compilation _CPPv4N6gccjit7context7compileEv}@anchor{147}@anchor{cp/topics/compilation _CPPv3N6gccjit7context7compileEv}@anchor{34b}@anchor{cp/topics/compilation _CPPv2N6gccjit7context7compileEv}@anchor{34c}@anchor{cp/topics/compilation gccjit context compile}@anchor{34d} 14169@deffn {C++ Function} gcc_jit_result *gccjit::@ref{13d,,context}::compile () 14170 14171This calls into GCC and builds the code, returning a 14172@cite{gcc_jit_result *}. 14173 14174This is a thin wrapper around the 14175@ref{15,,gcc_jit_context_compile()} API entrypoint. 14176@end deffn 14177 14178@node Ahead-of-time compilation<2>,,In-memory compilation<2>,Compiling a context<2> 14179@anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{34e} 14180@subsubsection Ahead-of-time compilation 14181 14182 14183Although libgccjit is primarily aimed at just-in-time compilation, it 14184can also be used for implementing more traditional ahead-of-time 14185compilers, via the @ref{349,,gccjit;;context;;compile_to_file()} method. 14186 14187@geindex gccjit;;context;;compile_to_file (C++ function) 14188@anchor{cp/topics/compilation _CPPv4N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{349}@anchor{cp/topics/compilation _CPPv3N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{34f}@anchor{cp/topics/compilation _CPPv2N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{350}@anchor{cp/topics/compilation gccjit context compile_to_file__gcc_jit_output_kind cCP}@anchor{351} 14189@deffn {C++ Function} void gccjit::@ref{13d,,context}::compile_to_file (enum gcc_jit_output_kind, const char *output_path) 14190 14191Compile the @ref{13d,,gccjit;;context} to a file of the given 14192kind. 14193 14194This is a thin wrapper around the 14195@ref{4a,,gcc_jit_context_compile_to_file()} API entrypoint. 14196@end deffn 14197 14198@c Copyright (C) 2020-2021 Free Software Foundation, Inc. 14199@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 14200@c 14201@c This is free software: you can redistribute it and/or modify it 14202@c under the terms of the GNU General Public License as published by 14203@c the Free Software Foundation, either version 3 of the License, or 14204@c (at your option) any later version. 14205@c 14206@c This program is distributed in the hope that it will be useful, but 14207@c WITHOUT ANY WARRANTY; without even the implied warranty of 14208@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14209@c General Public License for more details. 14210@c 14211@c You should have received a copy of the GNU General Public License 14212@c along with this program. If not, see 14213@c <http://www.gnu.org/licenses/>. 14214 14215@node Using Assembly Language with libgccjit++,,Compiling a context<2>,Topic Reference<2> 14216@anchor{cp/topics/asm doc}@anchor{352}@anchor{cp/topics/asm using-assembly-language-with-libgccjit}@anchor{353} 14217@subsection Using Assembly Language with libgccjit++ 14218 14219 14220libgccjit has some support for directly embedding assembler instructions. 14221This is based on GCC’s support for inline @code{asm} in C code, and the 14222following assumes a familiarity with that functionality. See 14223How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html} 14224in GCC’s documentation, the “Extended Asm” section in particular. 14225 14226These entrypoints were added in @ref{122,,LIBGCCJIT_ABI_15}; you can test 14227for their presence using 14228 14229@quotation 14230 14231@example 14232#ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS 14233@end example 14234@end quotation 14235 14236@menu 14237* Adding assembler instructions within a function: Adding assembler instructions within a function<2>. 14238* Adding top-level assembler statements: Adding top-level assembler statements<2>. 14239 14240@end menu 14241 14242@node Adding assembler instructions within a function<2>,Adding top-level assembler statements<2>,,Using Assembly Language with libgccjit++ 14243@anchor{cp/topics/asm adding-assembler-instructions-within-a-function}@anchor{354} 14244@subsubsection Adding assembler instructions within a function 14245 14246 14247@geindex gccjit;;extended_asm (C++ class) 14248@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asmE}@anchor{355}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asmE}@anchor{356}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asmE}@anchor{357}@anchor{cp/topics/asm gccjit extended_asm}@anchor{358} 14249@deffn {C++ Class} gccjit::extended_asm 14250 14251A @cite{gccjit::extended_asm} represents an extended @code{asm} statement: a 14252series of low-level instructions inside a function that convert inputs 14253to outputs. 14254 14255@ref{355,,gccjit;;extended_asm} is a subclass of @ref{142,,gccjit;;object}. 14256It is a thin wrapper around the C API’s @ref{f1,,gcc_jit_extended_asm *}. 14257 14258To avoid having an API entrypoint with a very large number of 14259parameters, an extended @code{asm} statement is made in stages: 14260an initial call to create the @ref{355,,gccjit;;extended_asm}, 14261followed by calls to add operands and set other properties of the 14262statement. 14263 14264There are two API entrypoints for creating a @ref{355,,gccjit;;extended_asm}: 14265 14266 14267@itemize * 14268 14269@item 14270@ref{359,,gccjit;;block;;add_extended_asm()} for an @code{asm} statement with 14271no control flow, and 14272 14273@item 14274@ref{35a,,gccjit;;block;;end_with_extended_asm_goto()} for an @code{asm goto}. 14275@end itemize 14276 14277For example, to create the equivalent of: 14278 14279@example 14280 asm ("mov %1, %0\n\t" 14281 "add $1, %0" 14282 : "=r" (dst) 14283 : "r" (src)); 14284@end example 14285 14286the following API calls could be used: 14287 14288@example 14289 block.add_extended_asm ("mov %1, %0\n\t" 14290 "add $1, %0") 14291 .add_output_operand ("=r", dst) 14292 .add_input_operand ("r", src); 14293@end example 14294 14295@cartouche 14296@quotation Warning 14297When considering the numbering of operands within an 14298extended @code{asm} statement (e.g. the @code{%0} and @code{%1} 14299above), the equivalent to the C syntax is followed i.e. all 14300output operands, then all input operands, regardless of 14301what order the calls to 14302@ref{35b,,gccjit;;extended_asm;;add_output_operand()} and 14303@ref{35c,,gccjit;;extended_asm;;add_input_operand()} were made in. 14304@end quotation 14305@end cartouche 14306 14307As in the C syntax, operands can be given symbolic names to avoid having 14308to number them. For example, to create the equivalent of: 14309 14310@example 14311 asm ("bsfl %[aMask], %[aIndex]" 14312 : [aIndex] "=r" (Index) 14313 : [aMask] "r" (Mask) 14314 : "cc"); 14315@end example 14316 14317the following API calls could be used: 14318 14319@example 14320 block.add_extended_asm ("bsfl %[aMask], %[aIndex]") 14321 .add_output_operand ("aIndex", "=r", index) 14322 .add_input_operand ("aMask", "r", mask) 14323 .add_clobber ("cc"); 14324@end example 14325@end deffn 14326 14327@geindex gccjit;;block;;add_extended_asm (C++ function) 14328@anchor{cp/topics/asm _CPPv4N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{359}@anchor{cp/topics/asm _CPPv3N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{35d}@anchor{cp/topics/asm _CPPv2N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{35e}@anchor{cp/topics/asm gccjit block add_extended_asm__ssCR gccjit location}@anchor{35f} 14329@deffn {C++ Function} @ref{355,,extended_asm} gccjit::@ref{153,,block}::add_extended_asm (const std::string &asm_template, gccjit::location loc = location()) 14330 14331Create a @ref{355,,gccjit;;extended_asm} for an extended @code{asm} statement 14332with no control flow (i.e. without the @code{goto} qualifier). 14333 14334The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate} 14335within C’s extended @code{asm} syntax. It must be non-NULL. The call takes 14336a copy of the underlying string, so it is valid to pass in a pointer to 14337an on-stack buffer. 14338@end deffn 14339 14340@geindex gccjit;;block;;end_with_extended_asm_goto (C++ function) 14341@anchor{cp/topics/asm _CPPv4N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{35a}@anchor{cp/topics/asm _CPPv3N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{360}@anchor{cp/topics/asm _CPPv2N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{361}@anchor{cp/topics/asm gccjit block end_with_extended_asm_goto__ssCR std vector block blockP location}@anchor{362} 14342@deffn {C++ Function} @ref{355,,extended_asm} gccjit::@ref{153,,block}::end_with_extended_asm_goto (const std::string &asm_template, std::vector<block> goto_blocks, block *fallthrough_block, location loc = location()) 14343 14344Create a @ref{355,,gccjit;;extended_asm} for an extended @code{asm} statement 14345that may perform jumps, and use it to terminate the given block. 14346This is equivalent to the @code{goto} qualifier in C’s extended @code{asm} 14347syntax. 14348 14349For example, to create the equivalent of: 14350 14351@example 14352 asm goto ("btl %1, %0\n\t" 14353 "jc %l[carry]" 14354 : // No outputs 14355 : "r" (p1), "r" (p2) 14356 : "cc" 14357 : carry); 14358@end example 14359 14360the following API calls could be used: 14361 14362@example 14363 const char *asm_template = 14364 (use_name 14365 ? /* Label referred to by name: "%l[carry]". */ 14366 ("btl %1, %0\n\t" 14367 "jc %l[carry]") 14368 : /* Label referred to numerically: "%l2". */ 14369 ("btl %1, %0\n\t" 14370 "jc %l2")); 14371 14372 std::vector<gccjit::block> goto_blocks (@{b_carry@}); 14373 gccjit::extended_asm ext_asm 14374 = (b_start.end_with_extended_asm_goto (asm_template, 14375 goto_blocks, 14376 &b_fallthru) 14377 .add_input_operand ("r", p1) 14378 .add_input_operand ("r", p2) 14379 .add_clobber ("cc")); 14380@end example 14381 14382here referencing a @code{gcc_jit_block} named “carry”. 14383 14384@code{num_goto_blocks} corresponds to the @code{GotoLabels} parameter within C’s 14385extended @code{asm} syntax. The block names can be referenced within the 14386assembler template. 14387 14388@code{fallthrough_block} can be NULL. If non-NULL, it specifies the block 14389to fall through to after the statement. 14390 14391@cartouche 14392@quotation Note 14393This is needed since each @ref{153,,gccjit;;block} must have a 14394single exit point, as a basic block: you can’t jump from the 14395middle of a block. A “goto” is implicitly added after the 14396asm to handle the fallthrough case, which is equivalent to what 14397would have happened in the C case. 14398@end quotation 14399@end cartouche 14400@end deffn 14401 14402@geindex gccjit;;extended_asm;;set_volatile_flag (C++ function) 14403@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17set_volatile_flagEb}@anchor{363}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17set_volatile_flagEb}@anchor{364}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17set_volatile_flagEb}@anchor{365}@anchor{cp/topics/asm gccjit extended_asm set_volatile_flag__b}@anchor{366} 14404@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::set_volatile_flag (bool flag) 14405 14406Set whether the @ref{355,,gccjit;;extended_asm} has side-effects, equivalent to the 14407volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile} 14408qualifier in C’s extended asm syntax. 14409 14410For example, to create the equivalent of: 14411 14412@example 14413asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX. 14414 "shl $32, %%rdx\n\t" // Shift the upper bits left. 14415 "or %%rdx, %0" // 'Or' in the lower bits. 14416 : "=a" (msr) 14417 : 14418 : "rdx"); 14419@end example 14420 14421the following API calls could be used: 14422 14423@example 14424 gccjit::extended_asm ext_asm 14425 = block.add_extended_asm 14426 ("rdtsc\n\t" /* Returns the time in EDX:EAX. */ 14427 "shl $32, %%rdx\n\t" /* Shift the upper bits left. */ 14428 "or %%rdx, %0") /* 'Or' in the lower bits. */ 14429 .set_volatile_flag (true) 14430 .add_output_operand ("=a", msr) 14431 .add_clobber ("rdx"); 14432@end example 14433 14434where the @ref{355,,gccjit;;extended_asm} is flagged as volatile. 14435@end deffn 14436 14437@geindex gccjit;;extended_asm;;set_inline_flag (C++ function) 14438@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm15set_inline_flagEb}@anchor{367}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm15set_inline_flagEb}@anchor{368}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm15set_inline_flagEb}@anchor{369}@anchor{cp/topics/asm gccjit extended_asm set_inline_flag__b}@anchor{36a} 14439@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::set_inline_flag (bool flag) 14440 14441Set the equivalent of the 14442inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm} 14443qualifier in C’s extended @code{asm} syntax. 14444@end deffn 14445 14446@geindex gccjit;;extended_asm;;add_output_operand (C++ function) 14447@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{35b}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{36b}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{36c}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR ssCR gccjit lvalue}@anchor{36d} 14448@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_output_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::lvalue dest) 14449 14450Add an output operand to the extended @code{asm} statement. See the 14451Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands} 14452section of the documentation of the C syntax. 14453 14454@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of 14455C’s extended @code{asm} syntax, and specifies the symbolic name for the operand. 14456See the overload below for an alternative that does not supply a symbolic 14457name. 14458 14459@code{constraint} corresponds to the @code{constraint} component of C’s extended 14460@code{asm} syntax. 14461 14462@code{dest} corresponds to the @code{cvariablename} component of C’s extended 14463@code{asm} syntax. 14464 14465@example 14466// Example with a symbolic name ("aIndex"), the equivalent of: 14467// : [aIndex] "=r" (index) 14468ext_asm.add_output_operand ("aIndex", "=r", index); 14469@end example 14470 14471This function can’t be called on an @code{asm goto} as such instructions can’t 14472have outputs; see the 14473Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels} 14474section of GCC’s “Extended Asm” documentation. 14475@end deffn 14476 14477@geindex gccjit;;extended_asm;;add_output_operand (C++ function) 14478@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{36e}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{36f}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{370}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR gccjit lvalue}@anchor{371} 14479@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_output_operand (const std::string &constraint, gccjit::lvalue dest) 14480 14481As above, but don’t supply a symbolic name for the operand. 14482 14483@example 14484// Example without a symbolic name, the equivalent of: 14485// : "=r" (dst) 14486ext_asm.add_output_operand ("=r", dst); 14487@end example 14488@end deffn 14489 14490@geindex gccjit;;extended_asm;;add_input_operand (C++ function) 14491@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{35c}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{372}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{373}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR ssCR gccjit rvalue}@anchor{374} 14492@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_input_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::rvalue src) 14493 14494Add an input operand to the extended @code{asm} statement. See the 14495Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands} 14496section of the documentation of the C syntax. 14497 14498@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component 14499of C’s extended @code{asm} syntax. See the overload below for an alternative 14500that does not supply a symbolic name. 14501 14502@code{constraint} corresponds to the @code{constraint} component of C’s extended 14503@code{asm} syntax. 14504 14505@code{src} corresponds to the @code{cexpression} component of C’s extended 14506@code{asm} syntax. 14507 14508@example 14509// Example with a symbolic name ("aMask"), the equivalent of: 14510// : [aMask] "r" (Mask) 14511ext_asm.add_input_operand ("aMask", "r", mask); 14512@end example 14513@end deffn 14514 14515@geindex gccjit;;extended_asm;;add_input_operand (C++ function) 14516@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{375}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{376}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{377}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR gccjit rvalue}@anchor{378} 14517@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_input_operand (const std::string &constraint, gccjit::rvalue src) 14518 14519As above, but don’t supply a symbolic name for the operand. 14520 14521@example 14522// Example without a symbolic name, the equivalent of: 14523// : "r" (src) 14524ext_asm.add_input_operand ("r", src); 14525@end example 14526@end deffn 14527 14528@geindex gccjit;;extended_asm;;add_clobber (C++ function) 14529@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{379}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{37a}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{37b}@anchor{cp/topics/asm gccjit extended_asm add_clobber__ssCR}@anchor{37c} 14530@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_clobber (const std::string &victim) 14531 14532Add @cite{victim} to the list of registers clobbered by the extended @code{asm} 14533statement. See the 14534Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#} 14535section of the documentation of the C syntax. 14536 14537Statements with multiple clobbers will require multiple calls, one per 14538clobber. 14539 14540For example: 14541 14542@example 14543ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory"); 14544@end example 14545@end deffn 14546 14547@node Adding top-level assembler statements<2>,,Adding assembler instructions within a function<2>,Using Assembly Language with libgccjit++ 14548@anchor{cp/topics/asm adding-top-level-assembler-statements}@anchor{37d} 14549@subsubsection Adding top-level assembler statements 14550 14551 14552In addition to creating extended @code{asm} instructions within a function, 14553there is support for creating “top-level” assembler statements, outside 14554of any function. 14555 14556@geindex gccjit;;context;;add_top_level_asm (C++ function) 14557@anchor{cp/topics/asm _CPPv4N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{37e}@anchor{cp/topics/asm _CPPv3N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{37f}@anchor{cp/topics/asm _CPPv2N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{380}@anchor{cp/topics/asm gccjit context add_top_level_asm__cCP gccjit location}@anchor{381} 14558@deffn {C++ Function} void gccjit::@ref{13d,,context}::add_top_level_asm (const char *asm_stmts, gccjit::location loc = location()) 14559 14560Create a set of top-level asm statements, analogous to those created 14561by GCC’s “basic” @code{asm} syntax in C at file scope. 14562 14563For example, to create the equivalent of: 14564 14565@example 14566 asm ("\t.pushsection .text\n" 14567 "\t.globl add_asm\n" 14568 "\t.type add_asm, @@function\n" 14569 "add_asm:\n" 14570 "\tmovq %rdi, %rax\n" 14571 "\tadd %rsi, %rax\n" 14572 "\tret\n" 14573 "\t.popsection\n"); 14574@end example 14575 14576the following API calls could be used: 14577 14578@example 14579 ctxt.add_top_level_asm ("\t.pushsection .text\n" 14580 "\t.globl add_asm\n" 14581 "\t.type add_asm, @@function\n" 14582 "add_asm:\n" 14583 "\tmovq %rdi, %rax\n" 14584 "\tadd %rsi, %rax\n" 14585 "\tret\n" 14586 "\t# some asm here\n" 14587 "\t.popsection\n"); 14588@end example 14589@end deffn 14590 14591@c Copyright (C) 2014-2021 Free Software Foundation, Inc. 14592@c Originally contributed by David Malcolm <dmalcolm@redhat.com> 14593@c 14594@c This is free software: you can redistribute it and/or modify it 14595@c under the terms of the GNU General Public License as published by 14596@c the Free Software Foundation, either version 3 of the License, or 14597@c (at your option) any later version. 14598@c 14599@c This program is distributed in the hope that it will be useful, but 14600@c WITHOUT ANY WARRANTY; without even the implied warranty of 14601@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14602@c General Public License for more details. 14603@c 14604@c You should have received a copy of the GNU General Public License 14605@c along with this program. If not, see 14606@c <http://www.gnu.org/licenses/>. 14607 14608@node Internals,Indices and tables,C++ bindings for libgccjit,Top 14609@anchor{internals/index doc}@anchor{382}@anchor{internals/index internals}@anchor{383} 14610@chapter Internals 14611 14612 14613@menu 14614* Working on the JIT library:: 14615* Running the test suite:: 14616* Environment variables:: 14617* Packaging notes:: 14618* Overview of code structure:: 14619* Design notes:: 14620* Submitting patches:: 14621 14622@end menu 14623 14624@node Working on the JIT library,Running the test suite,,Internals 14625@anchor{internals/index working-on-the-jit-library}@anchor{384} 14626@section Working on the JIT library 14627 14628 14629Having checked out the source code (to “src”), you can configure and build 14630the JIT library like this: 14631 14632@example 14633mkdir build 14634mkdir install 14635PREFIX=$(pwd)/install 14636cd build 14637../src/configure \ 14638 --enable-host-shared \ 14639 --enable-languages=jit,c++ \ 14640 --disable-bootstrap \ 14641 --enable-checking=release \ 14642 --prefix=$PREFIX 14643nice make -j4 # altering the "4" to however many cores you have 14644@end example 14645 14646This should build a libgccjit.so within jit/build/gcc: 14647 14648@example 14649[build] $ file gcc/libgccjit.so* 14650gcc/libgccjit.so: symbolic link to `libgccjit.so.0' 14651gcc/libgccjit.so.0: symbolic link to `libgccjit.so.0.0.1' 14652gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped 14653@end example 14654 14655Here’s what those configuration options mean: 14656 14657@geindex command line option; --enable-host-shared 14658@anchor{internals/index cmdoption-enable-host-shared}@anchor{385} 14659@deffn {Option} @w{-}@w{-}enable@w{-}host@w{-}shared 14660 14661Configuring with this option means that the compiler is built as 14662position-independent code, which incurs a slight performance hit, 14663but it necessary for a shared library. 14664@end deffn 14665 14666@geindex command line option; --enable-languages=jit@comma{}c++ 14667@anchor{internals/index cmdoption-enable-languages}@anchor{386} 14668@deffn {Option} @w{-}@w{-}enable@w{-}languages=jit,c++ 14669 14670This specifies which frontends to build. The JIT library looks like 14671a frontend to the rest of the code. 14672 14673The C++ portion of the JIT test suite requires the C++ frontend to be 14674enabled at configure-time, or you may see errors like this when 14675running the test suite: 14676 14677@example 14678xgcc: error: /home/david/jit/src/gcc/testsuite/jit.dg/test-quadratic.cc: C++ compiler not installed on this system 14679c++: error trying to exec 'cc1plus': execvp: No such file or directory 14680@end example 14681@end deffn 14682 14683@geindex command line option; --disable-bootstrap 14684@anchor{internals/index cmdoption-disable-bootstrap}@anchor{387} 14685@deffn {Option} @w{-}@w{-}disable@w{-}bootstrap 14686 14687For hacking on the “jit” subdirectory, performing a full 14688bootstrap can be overkill, since it’s unused by a bootstrap. However, 14689when submitting patches, you should remove this option, to ensure that 14690the compiler can still bootstrap itself. 14691@end deffn 14692 14693@geindex command line option; --enable-checking=release 14694@anchor{internals/index cmdoption-enable-checking}@anchor{388} 14695@deffn {Option} @w{-}@w{-}enable@w{-}checking=release 14696 14697The compile can perform extensive self-checking as it runs, useful when 14698debugging, but slowing things down. 14699 14700For maximum speed, configure with @code{--enable-checking=release} to 14701disable this self-checking. 14702@end deffn 14703 14704@node Running the test suite,Environment variables,Working on the JIT library,Internals 14705@anchor{internals/index running-the-test-suite}@anchor{389} 14706@section Running the test suite 14707 14708 14709@example 14710[build] $ cd gcc 14711[gcc] $ make check-jit RUNTESTFLAGS="-v -v -v" 14712@end example 14713 14714A summary of the tests can then be seen in: 14715 14716@example 14717jit/build/gcc/testsuite/jit/jit.sum 14718@end example 14719 14720and detailed logs in: 14721 14722@example 14723jit/build/gcc/testsuite/jit/jit.log 14724@end example 14725 14726The test executables are normally deleted after each test is run. For 14727debugging, they can be preserved by setting 14728@geindex PRESERVE_EXECUTABLES 14729@geindex environment variable; PRESERVE_EXECUTABLES 14730@code{PRESERVE_EXECUTABLES} 14731in the environment. If so, they can then be seen as: 14732 14733@example 14734jit/build/gcc/testsuite/jit/*.exe 14735@end example 14736 14737which can be run independently. 14738 14739You can compile and run individual tests by passing “jit.exp=TESTNAME” to RUNTESTFLAGS e.g.: 14740 14741@example 14742[gcc] $ PRESERVE_EXECUTABLES= \ 14743 make check-jit \ 14744 RUNTESTFLAGS="-v -v -v jit.exp=test-factorial.c" 14745@end example 14746 14747and once a test has been compiled, you can debug it directly: 14748 14749@example 14750[gcc] $ PATH=.:$PATH \ 14751 LD_LIBRARY_PATH=. \ 14752 LIBRARY_PATH=. \ 14753 gdb --args \ 14754 testsuite/jit/test-factorial.c.exe 14755@end example 14756 14757@menu 14758* Running under valgrind:: 14759 14760@end menu 14761 14762@node Running under valgrind,,,Running the test suite 14763@anchor{internals/index running-under-valgrind}@anchor{38a} 14764@subsection Running under valgrind 14765 14766 14767The jit testsuite detects if 14768@geindex RUN_UNDER_VALGRIND 14769@geindex environment variable; RUN_UNDER_VALGRIND 14770@code{RUN_UNDER_VALGRIND} is present in the 14771environment (with any value). If it is present, it runs the test client 14772code under valgrind@footnote{http://valgrind.org}, 14773specifcally, the default 14774memcheck@footnote{http://valgrind.org/docs/manual/mc-manual.html} 14775tool with 14776--leak-check=full@footnote{http://valgrind.org/docs/manual/mc-manual.html#opt.leak-check}. 14777 14778It automatically parses the output from valgrind, injecting XFAIL results if 14779any issues are found, or PASS results if the output is clean. The output 14780is saved to @code{TESTNAME.exe.valgrind.txt}. 14781 14782For example, the following invocation verbosely runs the testcase 14783@code{test-sum-of-squares.c} under valgrind, showing an issue: 14784 14785@example 14786$ RUN_UNDER_VALGRIND= \ 14787 make check-jit \ 14788 RUNTESTFLAGS="-v -v -v jit.exp=test-sum-of-squares.c" 14789 14790(...verbose log contains detailed valgrind errors, if any...) 14791 14792 === jit Summary === 14793 14794# of expected passes 28 14795# of expected failures 2 14796 14797$ less testsuite/jit/jit.sum 14798(...other results...) 14799XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: definitely lost: 8 bytes in 1 blocks 14800XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: unsuppressed errors: 1 14801(...other results...) 14802 14803$ less testsuite/jit/test-sum-of-squares.c.exe.valgrind.txt 14804(...shows full valgrind report for this test case...) 14805@end example 14806 14807When running under valgrind, it’s best to have configured gcc with 14808@code{--enable-valgrind-annotations}, which automatically suppresses 14809various known false positives. 14810 14811@node Environment variables,Packaging notes,Running the test suite,Internals 14812@anchor{internals/index environment-variables}@anchor{38b} 14813@section Environment variables 14814 14815 14816When running client code against a locally-built libgccjit, three 14817environment variables need to be set up: 14818 14819@geindex environment variable; LD_LIBRARY_PATH 14820@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{38c} 14821@deffn {Environment Variable} LD_LIBRARY_PATH 14822 14823@quotation 14824 14825@cite{libgccjit.so} is dynamically linked into client code, so if running 14826against a locally-built library, @code{LD_LIBRARY_PATH} needs to be set 14827up appropriately. The library can be found within the “gcc” 14828subdirectory of the build tree: 14829@end quotation 14830 14831@example 14832$ file libgccjit.so* 14833libgccjit.so: symbolic link to `libgccjit.so.0' 14834libgccjit.so.0: symbolic link to `libgccjit.so.0.0.1' 14835libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped 14836@end example 14837@end deffn 14838 14839@geindex environment variable; PATH 14840@anchor{internals/index envvar-PATH}@anchor{38d} 14841@deffn {Environment Variable} PATH 14842 14843The library uses a driver executable for converting from .s assembler 14844files to .so shared libraries. Specifically, it looks for a name 14845expanded from 14846@code{$@{target_noncanonical@}-gcc-$@{gcc_BASEVER@}$@{exeext@}} 14847such as @code{x86_64-unknown-linux-gnu-gcc-5.0.0}. 14848 14849Hence @code{PATH} needs to include a directory where the library can 14850locate this executable. 14851 14852The executable is normally installed to the installation bindir 14853(e.g. /usr/bin), but a copy is also created within the “gcc” 14854subdirectory of the build tree for running the testsuite, and for ease 14855of development. 14856@end deffn 14857 14858@geindex environment variable; LIBRARY_PATH 14859@anchor{internals/index envvar-LIBRARY_PATH}@anchor{38e} 14860@deffn {Environment Variable} LIBRARY_PATH 14861 14862The driver executable invokes the linker, and the latter needs to locate 14863support libraries needed by the generated code, or you will see errors 14864like: 14865 14866@example 14867ld: cannot find crtbeginS.o: No such file or directory 14868ld: cannot find -lgcc 14869ld: cannot find -lgcc_s 14870@end example 14871 14872Hence if running directly from a locally-built copy (without installing), 14873@code{LIBRARY_PATH} needs to contain the “gcc” subdirectory of the build 14874tree. 14875@end deffn 14876 14877For example, to run a binary that uses the library against a non-installed 14878build of the library in LIBGCCJIT_BUILD_DIR you need an invocation of the 14879client code like this, to preprend the dir to each of the environment 14880variables: 14881 14882@example 14883$ LD_LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LD_LIBRARY_PATH) \ 14884 PATH=$(LIBGCCJIT_BUILD_DIR):$(PATH) \ 14885 LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LIBRARY_PATH) \ 14886 ./jit-hello-world 14887hello world 14888@end example 14889 14890@node Packaging notes,Overview of code structure,Environment variables,Internals 14891@anchor{internals/index packaging-notes}@anchor{38f} 14892@section Packaging notes 14893 14894 14895The configure-time option @ref{385,,--enable-host-shared} is needed when 14896building the jit in order to get position-independent code. This will 14897slow down the regular compiler by a few percent. Hence when packaging gcc 14898with libgccjit, please configure and build twice: 14899 14900@quotation 14901 14902 14903@itemize * 14904 14905@item 14906once without @ref{385,,--enable-host-shared} for most languages, and 14907 14908@item 14909once with @ref{385,,--enable-host-shared} for the jit 14910@end itemize 14911@end quotation 14912 14913For example: 14914 14915@example 14916# Configure and build with --enable-host-shared 14917# for the jit: 14918mkdir configuration-for-jit 14919pushd configuration-for-jit 14920$(SRCDIR)/configure \ 14921 --enable-host-shared \ 14922 --enable-languages=jit \ 14923 --prefix=$(DESTDIR) 14924make 14925popd 14926 14927# Configure and build *without* --enable-host-shared 14928# for maximum speed: 14929mkdir standard-configuration 14930pushd standard-configuration 14931$(SRCDIR)/configure \ 14932 --enable-languages=all \ 14933 --prefix=$(DESTDIR) 14934make 14935popd 14936 14937# Both of the above are configured to install to $(DESTDIR) 14938# Install the configuration with --enable-host-shared first 14939# *then* the one without, so that the faster build 14940# of "cc1" et al overwrites the slower build. 14941pushd configuration-for-jit 14942make install 14943popd 14944 14945pushd standard-configuration 14946make install 14947popd 14948@end example 14949 14950@node Overview of code structure,Design notes,Packaging notes,Internals 14951@anchor{internals/index overview-of-code-structure}@anchor{390} 14952@section Overview of code structure 14953 14954 14955The library is implemented in C++. The source files have the @code{.c} 14956extension for legacy reasons. 14957 14958 14959@itemize * 14960 14961@item 14962@code{libgccjit.c} implements the API entrypoints. It performs error 14963checking, then calls into classes of the gcc::jit::recording namespace 14964within @code{jit-recording.c} and @code{jit-recording.h}. 14965 14966@item 14967The gcc::jit::recording classes (within @code{jit-recording.c} and 14968@code{jit-recording.h}) record the API calls that are made: 14969 14970@quotation 14971 14972@example 14973 14974 /* Indentation indicates inheritance: */ 14975 class context; 14976 class memento; 14977 class string; 14978 class location; 14979 class type; 14980 class function_type; 14981 class compound_type; 14982 class struct_; 14983 class union_; 14984 class vector_type; 14985 class field; 14986 class bitfield; 14987 class fields; 14988 class function; 14989 class block; 14990 class rvalue; 14991 class lvalue; 14992 class local; 14993 class global; 14994 class param; 14995 class base_call; 14996 class function_pointer; 14997 class statement; 14998 class extended_asm; 14999 class case_; 15000 class top_level_asm; 15001 15002@end example 15003@end quotation 15004 15005@item 15006When the context is compiled, the gcc::jit::playback classes (within 15007@code{jit-playback.c} and @code{jit-playback.h}) replay the API calls 15008within langhook:parse_file: 15009 15010@quotation 15011 15012@example 15013 15014 /* Indentation indicates inheritance: */ 15015 class context; 15016 class wrapper; 15017 class type; 15018 class compound_type; 15019 class field; 15020 class function; 15021 class block; 15022 class rvalue; 15023 class lvalue; 15024 class param; 15025 class source_file; 15026 class source_line; 15027 class location; 15028 class case_; 15029 15030@end example 15031 15032@example 15033Client Code . Generated . libgccjit.so 15034 . code . 15035 . . JIT API . JIT "Frontend". (libbackend.a) 15036.................................................................................... 15037 │ . . . . 15038 ──────────────────────────> . . 15039 . . │ . . 15040 . . V . . 15041 . . ──> libgccjit.c . 15042 . . │ (error-checking). 15043 . . │ . 15044 . . ──> jit-recording.c 15045 . . (record API calls) 15046 . . <─────── . 15047 . . │ . . 15048 <─────────────────────────── . . 15049 │ . . . . 15050 │ . . . . 15051 V . . gcc_jit_context_compile . 15052 ──────────────────────────> . . 15053 . . │ start of recording::context::compile () 15054 . . │ . . 15055 . . │ start of playback::context::compile () 15056 . . │ (create tempdir) . 15057 . . │ . . 15058 . . │ ACQUIRE MUTEX . 15059 . . │ . . 15060 . . V───────────────────────> toplev::main (for now) 15061 . . . . │ 15062 . . . . (various code) 15063 . . . . │ 15064 . . . . V 15065 . . . <───────────────── langhook:parse_file 15066 . . . │ . 15067 . . . │ (jit_langhook_parse_file) 15068 . . . │ . 15069..........................................│..................VVVVVVVVVVVVV... 15070 . . . │ . No GC in here 15071 . . . │ jit-playback.c 15072 . . . │ (playback of API calls) 15073 . . . ───────────────> creation of functions, 15074 . . . . types, expression trees 15075 . . . <──────────────── etc 15076 . . . │(handle_locations: add locations to 15077 . . . │ linemap and associate them with trees) 15078 . . . │ . 15079 . . . │ . No GC in here 15080..........................................│..................AAAAAAAAAAAAA... 15081 . . . │ for each function 15082 . . . ──> postprocess 15083 . . . │ . 15084 . . . ────────────> cgraph_finalize_function 15085 . . . <──────────── 15086 . . . <── . 15087 . . . │ . 15088 . . . ──────────────────> (end of 15089 . . . . │ langhook_parse_file) 15090 . . . . │ 15091 . . . . (various code) 15092 . . . . │ 15093 . . . . ↓ 15094 . . . <───────────────── langhook:write_globals 15095 . . . │ . 15096 . . . │ (jit_langhook_write_globals) 15097 . . . │ . 15098 . . . │ . 15099 . . . ──────────────────> finalize_compilation_unit 15100 . . . . │ 15101 . . . . (the middle─end and backend) 15102 . . . . ↓ 15103 . . <───────────────────────────── end of toplev::main 15104 . . │ . . 15105 . . V───────────────────────> toplev::finalize 15106 . . . . │ (purge internal state) 15107 . . <──────────────────────── end of toplev::finalize 15108 . . │ . . 15109 . . V─> playback::context::postprocess: 15110 . . │ . . 15111 . . │ (assuming an in-memory compile): 15112 . . │ . . 15113 . . --> Convert assembler to DSO, via embedded 15114 . . copy of driver: 15115 . . driver::main () 15116 . . invocation of "as" 15117 . . invocation of "ld" 15118 . . driver::finalize () 15119 . . <---- 15120 . . │ . . 15121 . . │ . Load DSO (dlopen "fake.so") 15122 . . │ . . 15123 . . │ . Bundle it up in a jit::result 15124 . . <── . . 15125 . . │ . . 15126 . . │ RELEASE MUTEX . 15127 . . │ . . 15128 . . │ end of playback::context::compile () 15129 . . │ . . 15130 . . │ playback::context dtor 15131 . . ──> . . 15132 . . │ Normally we cleanup the tempdir here: 15133 . . │ ("fake.so" is unlinked from the 15134 . . │ filesystem at this point) 15135 . . │ If the client code requested debuginfo, the 15136 . . │ cleanup happens later (in gcc_jit_result_release) 15137 . . │ to make it easier on the debugger (see PR jit/64206) 15138 . . <── . . 15139 . . │ . . 15140 . . │ end of recording::context::compile () 15141 <─────────────────────────── . . 15142 │ . . . . 15143 V . . gcc_jit_result_get_code . 15144 ──────────────────────────> . . 15145 . . │ dlsym () within loaded DSO 15146 <─────────────────────────── . . 15147 Get (void*). . . . 15148 │ . . . . 15149 │ Call it . . . . 15150 ───────────────> . . . 15151 . │ . . . 15152 . │ . . . 15153 <─────────────── . . . 15154 │ . . . . 15155etc│ . . . . 15156 │ . . . . 15157 V . . gcc_jit_result_release . 15158 ──────────────────────────> . . 15159 . . │ dlclose () the loaded DSO 15160 . . │ (code becomes uncallable) 15161 . . │ . . 15162 . . │ If the client code requested debuginfo, then 15163 . . │ cleanup of the tempdir was delayed. 15164 . . │ If that was the case, clean it up now. 15165 <─────────────────────────── . . 15166 │ . . . . 15167@end example 15168@end quotation 15169@end itemize 15170 15171Here is a high-level summary from @code{jit-common.h}: 15172 15173@quotation 15174 15175In order to allow jit objects to be usable outside of a compile 15176whilst working with the existing structure of GCC’s code the 15177C API is implemented in terms of a gcc::jit::recording::context, 15178which records the calls made to it. 15179 15180When a gcc_jit_context is compiled, the recording context creates a 15181playback context. The playback context invokes the bulk of the GCC 15182code, and within the “frontend” parsing hook, plays back the recorded 15183API calls, creating GCC tree objects. 15184 15185So there are two parallel families of classes: those relating to 15186recording, and those relating to playback: 15187 15188 15189@itemize * 15190 15191@item 15192Visibility: recording objects are exposed back to client code, 15193whereas playback objects are internal to the library. 15194 15195@item 15196Lifetime: recording objects have a lifetime equal to that of the 15197recording context that created them, whereas playback objects only 15198exist within the frontend hook. 15199 15200@item 15201Memory allocation: recording objects are allocated by the recording 15202context, and automatically freed by it when the context is released, 15203whereas playback objects are allocated within the GC heap, and 15204garbage-collected; they can own GC-references. 15205 15206@item 15207Integration with rest of GCC: recording objects are unrelated to the 15208rest of GCC, whereas playback objects are wrappers around “tree” 15209instances. Hence you can’t ask a recording rvalue or lvalue what its 15210type is, whereas you can for a playback rvalue of lvalue (since it 15211can work with the underlying GCC tree nodes). 15212 15213@item 15214Instancing: There can be multiple recording contexts “alive” at once 15215(albeit it only one compiling at once), whereas there can only be one 15216playback context alive at one time (since it interacts with the GC). 15217@end itemize 15218 15219Ultimately if GCC could support multiple GC heaps and contexts, and 15220finer-grained initialization, then this recording vs playback 15221distinction could be eliminated. 15222 15223During a playback, we associate objects from the recording with 15224their counterparts during this playback. For simplicity, we store this 15225within the recording objects, as @code{void *m_playback_obj}, casting it to 15226the appropriate playback object subclass. For these casts to make 15227sense, the two class hierarchies need to have the same structure. 15228 15229Note that the playback objects that @code{m_playback_obj} points to are 15230GC-allocated, but the recording objects don’t own references: 15231these associations only exist within a part of the code where 15232the GC doesn’t collect, and are set back to NULL before the GC can 15233run. 15234@end quotation 15235@anchor{internals/index example-of-log-file}@anchor{5c} 15236Another way to understand the structure of the code is to enable logging, 15237via @ref{5b,,gcc_jit_context_set_logfile()}. Here is an example of a log 15238generated via this call: 15239 15240@example 15241JIT: libgccjit (GCC) version 6.0.0 20150803 (experimental) (x86_64-pc-linux-gnu) 15242JIT: 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 15243JIT: entering: gcc_jit_context_set_str_option 15244JIT: GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe" 15245JIT: exiting: gcc_jit_context_set_str_option 15246JIT: entering: gcc_jit_context_set_int_option 15247JIT: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3 15248JIT: exiting: gcc_jit_context_set_int_option 15249JIT: entering: gcc_jit_context_set_bool_option 15250JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO: true 15251JIT: exiting: gcc_jit_context_set_bool_option 15252JIT: entering: gcc_jit_context_set_bool_option 15253JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false 15254JIT: exiting: gcc_jit_context_set_bool_option 15255JIT: entering: gcc_jit_context_set_bool_option 15256JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false 15257JIT: exiting: gcc_jit_context_set_bool_option 15258JIT: entering: gcc_jit_context_set_bool_option 15259JIT: GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true 15260JIT: exiting: gcc_jit_context_set_bool_option 15261JIT: entering: gcc_jit_context_set_bool_option 15262JIT: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false 15263JIT: exiting: gcc_jit_context_set_bool_option 15264JIT: entering: gcc_jit_context_get_type 15265JIT: exiting: gcc_jit_context_get_type 15266JIT: entering: gcc_jit_context_get_type 15267JIT: exiting: gcc_jit_context_get_type 15268JIT: entering: gcc_jit_context_new_param 15269JIT: exiting: gcc_jit_context_new_param 15270JIT: entering: gcc_jit_context_new_function 15271JIT: exiting: gcc_jit_context_new_function 15272JIT: entering: gcc_jit_context_new_param 15273JIT: exiting: gcc_jit_context_new_param 15274JIT: entering: gcc_jit_context_get_type 15275JIT: exiting: gcc_jit_context_get_type 15276JIT: entering: gcc_jit_context_new_function 15277JIT: exiting: gcc_jit_context_new_function 15278JIT: entering: gcc_jit_context_new_string_literal 15279JIT: exiting: gcc_jit_context_new_string_literal 15280JIT: entering: gcc_jit_function_new_block 15281JIT: exiting: gcc_jit_function_new_block 15282JIT: entering: gcc_jit_block_add_comment 15283JIT: exiting: gcc_jit_block_add_comment 15284JIT: entering: gcc_jit_context_new_call 15285JIT: exiting: gcc_jit_context_new_call 15286JIT: entering: gcc_jit_block_add_eval 15287JIT: exiting: gcc_jit_block_add_eval 15288JIT: entering: gcc_jit_block_end_with_void_return 15289JIT: exiting: gcc_jit_block_end_with_void_return 15290JIT: entering: gcc_jit_context_dump_reproducer_to_file 15291JIT: entering: void gcc::jit::recording::context::dump_reproducer_to_file(const char*) 15292JIT: exiting: void gcc::jit::recording::context::dump_reproducer_to_file(const char*) 15293JIT: exiting: gcc_jit_context_dump_reproducer_to_file 15294JIT: entering: gcc_jit_context_compile 15295JIT: in-memory compile of ctxt: 0x1283e20 15296JIT: entering: gcc::jit::result* gcc::jit::recording::context::compile() 15297JIT: GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe" 15298JIT: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3 15299JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO: true 15300JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false 15301JIT: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false 15302JIT: GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE: false 15303JIT: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false 15304JIT: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING: false 15305JIT: GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true 15306JIT: GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: false 15307JIT: gcc_jit_context_set_bool_allow_unreachable_blocks: false 15308JIT: gcc_jit_context_set_bool_use_external_driver: false 15309JIT: entering: void gcc::jit::recording::context::validate() 15310JIT: exiting: void gcc::jit::recording::context::validate() 15311JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*) 15312JIT: exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*) 15313JIT: entering: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*) 15314JIT: exiting: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*) 15315JIT: entering: void gcc::jit::playback::context::compile() 15316JIT: entering: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int) 15317JIT: exiting: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int) 15318JIT: entering: bool gcc::jit::tempdir::create() 15319JIT: m_path_template: /tmp/libgccjit-XXXXXX 15320JIT: m_path_tempdir: /tmp/libgccjit-CKq1M9 15321JIT: exiting: bool gcc::jit::tempdir::create() 15322JIT: entering: void gcc::jit::playback::context::acquire_mutex() 15323JIT: exiting: void gcc::jit::playback::context::acquire_mutex() 15324JIT: entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*) 15325JIT: reusing cached configure-time options 15326JIT: configure_time_options[0]: -mtune=generic 15327JIT: configure_time_options[1]: -march=x86-64 15328JIT: exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*) 15329JIT: entering: toplev::main 15330JIT: argv[0]: ./test-hello-world.c.exe 15331JIT: argv[1]: /tmp/libgccjit-CKq1M9/fake.c 15332JIT: argv[2]: -fPIC 15333JIT: argv[3]: -O3 15334JIT: argv[4]: -g 15335JIT: argv[5]: -quiet 15336JIT: argv[6]: --param 15337JIT: argv[7]: ggc-min-expand=0 15338JIT: argv[8]: --param 15339JIT: argv[9]: ggc-min-heapsize=0 15340JIT: argv[10]: -mtune=generic 15341JIT: argv[11]: -march=x86-64 15342JIT: entering: bool jit_langhook_init() 15343JIT: exiting: bool jit_langhook_init() 15344JIT: entering: void gcc::jit::playback::context::replay() 15345JIT: entering: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*) 15346JIT: exiting: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*) 15347JIT: entering: void gcc::jit::recording::context::disassociate_from_playback() 15348JIT: exiting: void gcc::jit::recording::context::disassociate_from_playback() 15349JIT: entering: void gcc::jit::playback::context::handle_locations() 15350JIT: exiting: void gcc::jit::playback::context::handle_locations() 15351JIT: entering: void gcc::jit::playback::function::build_stmt_list() 15352JIT: exiting: void gcc::jit::playback::function::build_stmt_list() 15353JIT: entering: void gcc::jit::playback::function::build_stmt_list() 15354JIT: exiting: void gcc::jit::playback::function::build_stmt_list() 15355JIT: entering: void gcc::jit::playback::function::postprocess() 15356JIT: exiting: void gcc::jit::playback::function::postprocess() 15357JIT: entering: void gcc::jit::playback::function::postprocess() 15358JIT: exiting: void gcc::jit::playback::function::postprocess() 15359JIT: exiting: void gcc::jit::playback::context::replay() 15360JIT: exiting: toplev::main 15361JIT: entering: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*) 15362JIT: exiting: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*) 15363JIT: entering: toplev::finalize 15364JIT: exiting: toplev::finalize 15365JIT: entering: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) 15366JIT: entering: void gcc::jit::playback::context::convert_to_dso(const char*) 15367JIT: entering: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) 15368JIT: entering: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*) 15369JIT: exiting: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*) 15370JIT: argv[0]: x86_64-unknown-linux-gnu-gcc-6.0.0 15371JIT: argv[1]: -m64 15372JIT: argv[2]: -shared 15373JIT: argv[3]: /tmp/libgccjit-CKq1M9/fake.s 15374JIT: argv[4]: -o 15375JIT: argv[5]: /tmp/libgccjit-CKq1M9/fake.so 15376JIT: argv[6]: -fno-use-linker-plugin 15377JIT: entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) 15378JIT: exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) 15379JIT: exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) 15380JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*) 15381JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso() 15382JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO was set: handing over tempdir to jit::result 15383JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*) 15384JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*) 15385JIT: exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso() 15386JIT: exiting: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) 15387JIT: entering: void gcc::jit::playback::context::release_mutex() 15388JIT: exiting: void gcc::jit::playback::context::release_mutex() 15389JIT: exiting: void gcc::jit::playback::context::compile() 15390JIT: entering: gcc::jit::playback::context::~context() 15391JIT: exiting: gcc::jit::playback::context::~context() 15392JIT: exiting: gcc::jit::result* gcc::jit::recording::context::compile() 15393JIT: gcc_jit_context_compile: returning (gcc_jit_result *)0x12f75d0 15394JIT: exiting: gcc_jit_context_compile 15395JIT: entering: gcc_jit_result_get_code 15396JIT: locating fnname: hello_world 15397JIT: entering: void* gcc::jit::result::get_code(const char*) 15398JIT: exiting: void* gcc::jit::result::get_code(const char*) 15399JIT: gcc_jit_result_get_code: returning (void *)0x7ff6b8cd87f0 15400JIT: exiting: gcc_jit_result_get_code 15401JIT: entering: gcc_jit_context_release 15402JIT: deleting ctxt: 0x1283e20 15403JIT: entering: gcc::jit::recording::context::~context() 15404JIT: exiting: gcc::jit::recording::context::~context() 15405JIT: exiting: gcc_jit_context_release 15406JIT: entering: gcc_jit_result_release 15407JIT: deleting result: 0x12f75d0 15408JIT: entering: virtual gcc::jit::result::~result() 15409JIT: entering: gcc::jit::tempdir::~tempdir() 15410JIT: unlinking .s file: /tmp/libgccjit-CKq1M9/fake.s 15411JIT: unlinking .so file: /tmp/libgccjit-CKq1M9/fake.so 15412JIT: removing tempdir: /tmp/libgccjit-CKq1M9 15413JIT: exiting: gcc::jit::tempdir::~tempdir() 15414JIT: exiting: virtual gcc::jit::result::~result() 15415JIT: exiting: gcc_jit_result_release 15416JIT: gcc::jit::logger::~logger() 15417@end example 15418 15419@node Design notes,Submitting patches,Overview of code structure,Internals 15420@anchor{internals/index design-notes}@anchor{391} 15421@section Design notes 15422 15423 15424It should not be possible for client code to cause an internal compiler 15425error. If this @emph{does} happen, the root cause should be isolated (perhaps 15426using @ref{5d,,gcc_jit_context_dump_reproducer_to_file()}) and the cause 15427should be rejected via additional checking. The checking ideally should 15428be within the libgccjit API entrypoints in libgccjit.c, since this is as 15429close as possible to the error; failing that, a good place is within 15430@code{recording::context::validate ()} in jit-recording.c. 15431 15432@node Submitting patches,,Design notes,Internals 15433@anchor{internals/index submitting-patches}@anchor{392} 15434@section Submitting patches 15435 15436 15437Please read the contribution guidelines for gcc at 15438@indicateurl{https://gcc.gnu.org/contribute.html}. 15439 15440Patches for the jit should be sent to both the 15441@email{gcc-patches@@gcc.gnu.org} and @email{jit@@gcc.gnu.org} mailing lists, 15442with “jit” and “PATCH” in the Subject line. 15443 15444You don’t need to do a full bootstrap for code that just touches the 15445@code{jit} and @code{testsuite/jit.dg} subdirectories. However, please run 15446@code{make check-jit} before submitting the patch, and mention the results 15447in your email (along with the host triple that the tests were run on). 15448 15449A good patch should contain the information listed in the 15450gcc contribution guide linked to above; for a @code{jit} patch, the patch 15451shold contain: 15452 15453@quotation 15454 15455 15456@itemize * 15457 15458@item 15459the code itself (for example, a new API entrypoint will typically 15460touch @code{libgccjit.h} and @code{.c}, along with support code in 15461@code{jit-recording.[ch]} and @code{jit-playback.[ch]} as appropriate) 15462 15463@item 15464test coverage 15465 15466@item 15467documentation for the C API 15468 15469@item 15470documentation for the C++ API 15471@end itemize 15472@end quotation 15473 15474A patch that adds new API entrypoints should also contain: 15475 15476@quotation 15477 15478 15479@itemize * 15480 15481@item 15482a feature macro in @code{libgccjit.h} so that client code that doesn’t 15483use a “configure” mechanism can still easily detect the presence of 15484the entrypoint. See e.g. @code{LIBGCCJIT_HAVE_SWITCH_STATEMENTS} (for 15485a category of entrypoints) and 15486@code{LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks} 15487(for an individual entrypoint). 15488 15489@item 15490a new ABI tag containing the new symbols (in @code{libgccjit.map}), so 15491that we can detect client code that uses them 15492 15493@item 15494Support for @ref{5d,,gcc_jit_context_dump_reproducer_to_file()}. Most 15495jit testcases attempt to dump their contexts to a .c file; @code{jit.exp} 15496then sanity-checks the generated c by compiling them (though 15497not running them). A new API entrypoint 15498needs to “know” how to write itself back out to C (by implementing 15499@code{gcc::jit::recording::memento::write_reproducer} for the appropriate 15500@code{memento} subclass). 15501 15502@item 15503C++ bindings for the new entrypoints (see @code{libgccjit++.h}); ideally 15504with test coverage, though the C++ API test coverage is admittedly 15505spotty at the moment 15506 15507@item 15508documentation for the new C entrypoints 15509 15510@item 15511documentation for the new C++ entrypoints 15512 15513@item 15514documentation for the new ABI tag (see @code{topics/compatibility.rst}). 15515@end itemize 15516@end quotation 15517 15518Depending on the patch you can either extend an existing test case, or 15519add a new test case. If you add an entirely new testcase: @code{jit.exp} 15520expects jit testcases to begin with @code{test-}, or @code{test-error-} (for a 15521testcase that generates an error on a @ref{8,,gcc_jit_context}). 15522 15523Every new testcase that doesn’t generate errors should also touch 15524@code{gcc/testsuite/jit.dg/all-non-failing-tests.h}: 15525 15526@quotation 15527 15528 15529@itemize * 15530 15531@item 15532Testcases that don’t generate errors should ideally be added to the 15533@code{testcases} array in that file; this means that, in addition 15534to being run standalone, they also get run within 15535@code{test-combination.c} (which runs all successful tests inside one 15536big @ref{8,,gcc_jit_context}), and @code{test-threads.c} (which runs all 15537successful tests in one process, each one running in a different 15538thread on a different @ref{8,,gcc_jit_context}). 15539 15540@cartouche 15541@quotation Note 15542Given that exported functions within a @ref{8,,gcc_jit_context} 15543must have unique names, and most testcases are run within 15544@code{test-combination.c}, this means that every jit-compiled test 15545function typically needs a name that’s unique across the entire 15546test suite. 15547@end quotation 15548@end cartouche 15549 15550@item 15551Testcases that aren’t to be added to the @code{testcases} array should 15552instead add a comment to the file clarifying why they’re not in that 15553array. See the file for examples. 15554@end itemize 15555@end quotation 15556 15557Typically a patch that touches the .rst documentation will also need the 15558texinfo to be regenerated. You can do this with 15559Sphinx 1.0@footnote{http://sphinx-doc.org/} or later by 15560running @code{make texinfo} within @code{SRCDIR/gcc/jit/docs}. Don’t do this 15561within the patch sent to the mailing list; it can often be relatively 15562large and inconsequential (e.g. anchor renumbering), rather like generated 15563“configure” changes from configure.ac. You can regenerate it when 15564committing to svn. 15565 15566@node Indices and tables,Index,Internals,Top 15567@anchor{index indices-and-tables}@anchor{393} 15568@unnumbered Indices and tables 15569 15570 15571 15572@itemize * 15573 15574@item 15575genindex 15576 15577@item 15578modindex 15579 15580@item 15581search 15582@end itemize 15583 15584@c Some notes: 15585@c 15586@c The Sphinx C domain appears to lack explicit support for enum values, 15587@c so I've been using :c:macro: for them. 15588@c 15589@c See http://sphinx-doc.org/domains.html#the-c-domain 15590 15591@node Index,,Indices and tables,Top 15592@unnumbered Index 15593 15594 15595@printindex ge 15596 15597 15598@c %**end of body 15599@bye 15600