From 86d0ac8876cf8b9eebed0ca3caa31a83dfc8a17d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 13 Jan 2015 22:14:46 +0000 Subject: [PATCH] jit: New API entrypoint: gcc_jit_context_dump_reproducer_to_file gcc/jit/ChangeLog: * docs/cp/topics/contexts.rst (Debugging): Add gccjit::context::dump_reproducer_to_file. * docs/internals/index.rst (Design notes): New section, discussing input validation and gcc_jit_context_dump_reproducer_to_file. * docs/topics/contexts.rst (Debugging): Add gcc_jit_context_dump_reproducer_to_file. * docs/_build/texinfo/libgccjit.texi: Regenerate. * jit-common.h (gcc::jit::dump::get_context): New accessor. * jit-recording.c: Include "hash-map.h". Within namespace ::gcc::jit... (dump::write): Flush each line. (dump::make_location): Pass false for new param "created_by_user". (class allocator): New class. (allocator::~allocator): New function. (allocator::xstrdup_printf): New function. (allocator::xstrdup_printf_va): New function. (class reproducer): New subclass of dump. (reproducer::reproducer): New function. (reproducer::write_params): New function. (reproducer::write_args): New function. (reproducer::make_identifier): New function. (reproducer::make_tmp_identifier): New function. (reproducer::get_identifier): New pair of functions. (reproducer::get_identifier_as_rvalue): New function. (reproducer::get_identifier_as_lvalue): New function. (reproducer::get_identifier_as_type): New function. (reproducer::xstrdup_printf): New function. (recording::context::context): Initialize m_toplevel_ctxt. (recording::context::new_location): Add param created_by_user. (str_option_reproducer_strings): New table of strings. (int_option_reproducer_strings): Likewise. (bool_option_reproducer_strings): Likewise. (get_type_enum_strings): Likewise. (names_of_function_kinds): Likewise. (global_kind_reproducer_strings): Likewise. (unary_op_reproducer_strings): Likewise. (binary_op_reproducer_strings): Likewise. (comparison_reproducer_strings): Likewise. Within namespace ::gcc::jit::recording::... (context::dump_reproducer_to_file): New function. (string::write_reproducer): Likewise. (location::write_reproducer): Likewise. (type::access_as_type): Likewise. (memento_of_get_type::write_reproducer): Likewise. (memento_of_get_pointer::write_reproducer): Likewise. (memento_of_get_const::write_reproducer): Likewise. (memento_of_get_volatile::write_reproducer): Likewise. (array_type::write_reproducer): Likewise. (function_type::write_reproducer): Likewise. (function_type::write_deferred_reproducer): Likewise. (field::write_reproducer): Likewise. (struct_::access_as_type): Likewise. (struct_::write_reproducer): Likewise. (union_::write_reproducer): Likewise. (fields::write_reproducer): Likewise. (rvalue::access_as_rvalue): Likewise. (lvalue::access_as_rvalue): Likewise. (lvalue::access_as_lvalue): Likewise. (param::access_as_rvalue): Likewise. (param::access_as_lvalue): Likewise. (param::write_reproducer): Likewise. (function::write_reproducer): Likewise. (block::write_reproducer): Likewise. (global::write_reproducer): Likewise. (memento_of_new_rvalue_from_const ::write_reproducer): Likewise. (memento_of_new_rvalue_from_const ::write_reproducer): Likewise. (memento_of_new_rvalue_from_const ::write_reproducer): Likewise. (memento_of_new_rvalue_from_const ::write_reproducer): Likewise. (memento_of_new_string_literal::write_reproducer): Likewise. (unary_op::write_reproducer): Likewise. (binary_op::write_reproducer): Likewise. (comparison::write_reproducer): Likewise. (cast::write_reproducer): Likewise. (call::write_reproducer): Likewise. (call_through_ptr::write_reproducer): Likewise. (array_access::write_reproducer): Likewise. (access_field_of_lvalue::write_reproducer): Likewise. (access_field_rvalue::write_reproducer): Likewise. (dereference_field_rvalue::write_reproducer): Likewise. (dereference_rvalue::write_reproducer): Likewise. (get_address_of_lvalue::write_reproducer): Likewise. (local::write_reproducer): Likewise. (eval::write_reproducer): Likewise. (assignment::write_reproducer): Likewise. (assignment_op::write_reproducer): Likewise. (comment::write_reproducer): Likewise. (conditional::write_reproducer): Likewise. (jump::write_reproducer): Likewise. (return_::write_reproducer): Likewise. * jit-recording.h (gcc::jit::reproducer): New forward declararion. Within namespace ::gcc::jit::recording::... (context::new_location): Add "created_by_user" param. (context::dump_reproducer_to_file): New method. (context::m_toplevel_ctxt): New field. (memento::write_reproducer): New pure virtual function. (memento::dyn_cast_location): New virtual function. (string::write_reproducer): (location::location): Add "created_by_user" param. (location::dyn_cast_location): New function. (location::created_by_user): New accessor. (location::write_reproducer): New function. (location::m_created_by_user): New field. (type::access_as_type): New virtual function. (location::write_reproducer): Likewise. (type::access_as_type): Likewise. (memento_of_get_type::write_reproducer): Likewise. (memento_of_get_pointer::write_reproducer): Likewise. (memento_of_get_const::write_reproducer): Likewise. (memento_of_get_volatile::write_reproducer): Likewise. (array_type::write_reproducer): Likewise. (function_type::write_reproducer): Likewise. (function_type::write_deferred_reproducer): Likewise. (field::write_reproducer): Likewise. (struct_::access_as_type): Likewise. (struct_::write_reproducer): Likewise. (union_::write_reproducer): Likewise. (union_::m_fields): Remove stray unused field. (fields::length): New accessor. (fields::get_field): New accessor. (fields::write_reproducer): New function. (rvalue::access_as_rvalue): Likewise. (lvalue::access_as_rvalue): Likewise. (lvalue::access_as_lvalue): Likewise. (param::access_as_rvalue): Likewise. (param::access_as_lvalue): Likewise. (param::write_reproducer): Likewise. (function::write_reproducer): Likewise. (block::write_reproducer): Likewise. (global::write_reproducer): Likewise. (memento_of_new_rvalue_from_const ::write_reproducer): Likewise. (memento_of_new_string_literal::write_reproducer): Likewise. (unary_op::write_reproducer): Likewise. (binary_op::write_reproducer): Likewise. (comparison::write_reproducer): Likewise. (cast::write_reproducer): Likewise. (call::write_reproducer): Likewise. (call_through_ptr::write_reproducer): Likewise. (array_access::write_reproducer): Likewise. (access_field_of_lvalue::write_reproducer): Likewise. (access_field_rvalue::write_reproducer): Likewise. (dereference_field_rvalue::write_reproducer): Likewise. (dereference_rvalue::write_reproducer): Likewise. (get_address_of_lvalue::write_reproducer): Likewise. (local::write_reproducer): Likewise. (eval::write_reproducer): Likewise. (assignment::write_reproducer): Likewise. (assignment_op::write_reproducer): Likewise. (comment::write_reproducer): Likewise. (conditional::write_reproducer): Likewise. (jump::write_reproducer): Likewise. (return_::write_reproducer): Likewise. * libgccjit++.h (gccjit::context::dump_reproducer_to_file): New. * libgccjit.c (gcc_jit_context_new_location): Pass "true" as param "created_by_user". (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. * libgccjit.h (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. * libgccjit.map (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. gcc/testsuite/ChangeLog: * jit.dg/harness.h (set_up_logging): Move string concatenation into... (concat_strings): New function. (dump_reproducer): New function. (test_jit): Call dump_reproducer. * jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer): New function. (jit-dg-test): Delete any generated reproducer from previous runs. Verify that a generated reproducer was created, and verify that it compiles. * jit.dg/test-nested-contexts.c (main): Call gcc_jit_context_dump_reproducer_to_file. From-SVN: r219564 --- gcc/jit/ChangeLog | 168 +++ gcc/jit/docs/_build/texinfo/libgccjit.texi | 823 ++++++----- gcc/jit/docs/cp/topics/contexts.rst | 10 + gcc/jit/docs/internals/index.rst | 10 + gcc/jit/docs/topics/contexts.rst | 24 + gcc/jit/jit-common.h | 2 + gcc/jit/jit-recording.c | 1462 ++++++++++++++++++- gcc/jit/jit-recording.h | 81 +- gcc/jit/libgccjit++.h | 9 + gcc/jit/libgccjit.c | 18 +- gcc/jit/libgccjit.h | 18 + gcc/jit/libgccjit.map | 1 + gcc/testsuite/ChangeLog | 15 + gcc/testsuite/jit.dg/harness.h | 47 +- gcc/testsuite/jit.dg/jit.exp | 71 + gcc/testsuite/jit.dg/test-nested-contexts.c | 8 + 16 files changed, 2354 insertions(+), 413 deletions(-) diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index dbc1dc692d0..d15a21424b2 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,171 @@ +2015-01-13 David Malcolm + + * docs/cp/topics/contexts.rst (Debugging): Add + gccjit::context::dump_reproducer_to_file. + * docs/internals/index.rst (Design notes): New section, + discussing input validation and + gcc_jit_context_dump_reproducer_to_file. + * docs/topics/contexts.rst (Debugging): Add + gcc_jit_context_dump_reproducer_to_file. + * docs/_build/texinfo/libgccjit.texi: Regenerate. + * jit-common.h (gcc::jit::dump::get_context): New accessor. + * jit-recording.c: Include "hash-map.h". + Within namespace ::gcc::jit... + (dump::write): Flush each line. + (dump::make_location): Pass false for new param "created_by_user". + (class allocator): New class. + (allocator::~allocator): New function. + (allocator::xstrdup_printf): New function. + (allocator::xstrdup_printf_va): New function. + (class reproducer): New subclass of dump. + (reproducer::reproducer): New function. + (reproducer::write_params): New function. + (reproducer::write_args): New function. + (reproducer::make_identifier): New function. + (reproducer::make_tmp_identifier): New function. + (reproducer::get_identifier): New pair of functions. + (reproducer::get_identifier_as_rvalue): New function. + (reproducer::get_identifier_as_lvalue): New function. + (reproducer::get_identifier_as_type): New function. + (reproducer::xstrdup_printf): New function. + (recording::context::context): Initialize m_toplevel_ctxt. + (recording::context::new_location): Add param created_by_user. + (str_option_reproducer_strings): New table of strings. + (int_option_reproducer_strings): Likewise. + (bool_option_reproducer_strings): Likewise. + (get_type_enum_strings): Likewise. + (names_of_function_kinds): Likewise. + (global_kind_reproducer_strings): Likewise. + (unary_op_reproducer_strings): Likewise. + (binary_op_reproducer_strings): Likewise. + (comparison_reproducer_strings): Likewise. + Within namespace ::gcc::jit::recording::... + (context::dump_reproducer_to_file): New function. + (string::write_reproducer): Likewise. + (location::write_reproducer): Likewise. + (type::access_as_type): Likewise. + (memento_of_get_type::write_reproducer): Likewise. + (memento_of_get_pointer::write_reproducer): Likewise. + (memento_of_get_const::write_reproducer): Likewise. + (memento_of_get_volatile::write_reproducer): Likewise. + (array_type::write_reproducer): Likewise. + (function_type::write_reproducer): Likewise. + (function_type::write_deferred_reproducer): Likewise. + (field::write_reproducer): Likewise. + (struct_::access_as_type): Likewise. + (struct_::write_reproducer): Likewise. + (union_::write_reproducer): Likewise. + (fields::write_reproducer): Likewise. + (rvalue::access_as_rvalue): Likewise. + (lvalue::access_as_rvalue): Likewise. + (lvalue::access_as_lvalue): Likewise. + (param::access_as_rvalue): Likewise. + (param::access_as_lvalue): Likewise. + (param::write_reproducer): Likewise. + (function::write_reproducer): Likewise. + (block::write_reproducer): Likewise. + (global::write_reproducer): Likewise. + (memento_of_new_rvalue_from_const ::write_reproducer): + Likewise. + (memento_of_new_rvalue_from_const ::write_reproducer): + Likewise. + (memento_of_new_rvalue_from_const ::write_reproducer): + Likewise. + (memento_of_new_rvalue_from_const ::write_reproducer): + Likewise. + (memento_of_new_string_literal::write_reproducer): Likewise. + (unary_op::write_reproducer): Likewise. + (binary_op::write_reproducer): Likewise. + (comparison::write_reproducer): Likewise. + (cast::write_reproducer): Likewise. + (call::write_reproducer): Likewise. + (call_through_ptr::write_reproducer): Likewise. + (array_access::write_reproducer): Likewise. + (access_field_of_lvalue::write_reproducer): Likewise. + (access_field_rvalue::write_reproducer): Likewise. + (dereference_field_rvalue::write_reproducer): Likewise. + (dereference_rvalue::write_reproducer): Likewise. + (get_address_of_lvalue::write_reproducer): Likewise. + (local::write_reproducer): Likewise. + (eval::write_reproducer): Likewise. + (assignment::write_reproducer): Likewise. + (assignment_op::write_reproducer): Likewise. + (comment::write_reproducer): Likewise. + (conditional::write_reproducer): Likewise. + (jump::write_reproducer): Likewise. + (return_::write_reproducer): Likewise. + * jit-recording.h (gcc::jit::reproducer): New forward declararion. + Within namespace ::gcc::jit::recording::... + (context::new_location): Add "created_by_user" param. + (context::dump_reproducer_to_file): New method. + (context::m_toplevel_ctxt): New field. + (memento::write_reproducer): New pure virtual function. + (memento::dyn_cast_location): New virtual function. + (string::write_reproducer): + (location::location): Add "created_by_user" param. + (location::dyn_cast_location): New function. + (location::created_by_user): New accessor. + (location::write_reproducer): New function. + (location::m_created_by_user): New field. + (type::access_as_type): New virtual function. + (location::write_reproducer): Likewise. + (type::access_as_type): Likewise. + (memento_of_get_type::write_reproducer): Likewise. + (memento_of_get_pointer::write_reproducer): Likewise. + (memento_of_get_const::write_reproducer): Likewise. + (memento_of_get_volatile::write_reproducer): Likewise. + (array_type::write_reproducer): Likewise. + (function_type::write_reproducer): Likewise. + (function_type::write_deferred_reproducer): Likewise. + (field::write_reproducer): Likewise. + (struct_::access_as_type): Likewise. + (struct_::write_reproducer): Likewise. + (union_::write_reproducer): Likewise. + (union_::m_fields): Remove stray unused field. + (fields::length): New accessor. + (fields::get_field): New accessor. + (fields::write_reproducer): New function. + (rvalue::access_as_rvalue): Likewise. + (lvalue::access_as_rvalue): Likewise. + (lvalue::access_as_lvalue): Likewise. + (param::access_as_rvalue): Likewise. + (param::access_as_lvalue): Likewise. + (param::write_reproducer): Likewise. + (function::write_reproducer): Likewise. + (block::write_reproducer): Likewise. + (global::write_reproducer): Likewise. + (memento_of_new_rvalue_from_const ::write_reproducer): + Likewise. + (memento_of_new_string_literal::write_reproducer): Likewise. + (unary_op::write_reproducer): Likewise. + (binary_op::write_reproducer): Likewise. + (comparison::write_reproducer): Likewise. + (cast::write_reproducer): Likewise. + (call::write_reproducer): Likewise. + (call_through_ptr::write_reproducer): Likewise. + (array_access::write_reproducer): Likewise. + (access_field_of_lvalue::write_reproducer): Likewise. + (access_field_rvalue::write_reproducer): Likewise. + (dereference_field_rvalue::write_reproducer): Likewise. + (dereference_rvalue::write_reproducer): Likewise. + (get_address_of_lvalue::write_reproducer): Likewise. + (local::write_reproducer): Likewise. + (eval::write_reproducer): Likewise. + (assignment::write_reproducer): Likewise. + (assignment_op::write_reproducer): Likewise. + (comment::write_reproducer): Likewise. + (conditional::write_reproducer): Likewise. + (jump::write_reproducer): Likewise. + (return_::write_reproducer): Likewise. + * libgccjit++.h (gccjit::context::dump_reproducer_to_file): New. + * libgccjit.c (gcc_jit_context_new_location): Pass "true" as + param "created_by_user". + (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. + * libgccjit.h (gcc_jit_context_dump_reproducer_to_file): New API + entrypoint. + * libgccjit.map (gcc_jit_context_dump_reproducer_to_file): New API + entrypoint. + 2015-01-12 David Malcolm * jit-recording.c (class gcc::jit::rvalue_usage_validator): New. diff --git a/gcc/jit/docs/_build/texinfo/libgccjit.texi b/gcc/jit/docs/_build/texinfo/libgccjit.texi index 07c93085442..8213f9a8d00 100644 --- a/gcc/jit/docs/_build/texinfo/libgccjit.texi +++ b/gcc/jit/docs/_build/texinfo/libgccjit.texi @@ -19,7 +19,7 @@ @copying @quotation -libgccjit 5.0.0 (experimental 20150112), January 12, 2015 +libgccjit 5.0.0 (experimental 20150113), January 13, 2015 David Malcolm @@ -319,6 +319,7 @@ Internals * Running the test suite:: * Environment variables:: * Overview of code structure:: +* Design notes:: Running the test suite @@ -4276,8 +4277,32 @@ current state of a context to the given path, whereas @pxref{54,,gcc_jit_context_set_logfile()} enables on-going logging of future activies on a context to the given @cite{FILE *}. +@geindex gcc_jit_context_dump_reproducer_to_file (C function) +@anchor{topics/contexts gcc_jit_context_dump_reproducer_to_file}@anchor{56} +@deffn {C Function} void gcc_jit_context_dump_reproducer_to_file (gcc_jit_context@w{ }*ctxt, const char@w{ }*path) + +Write C source code into @cite{path} that can be compiled into a +self-contained executable (i.e. with libgccjit as the only dependency). +The generated code will attempt to replay the API calls that have been +made into the given context. + +This may be useful when debugging the library or client code, for +reducing a complicated recipe for reproducing a bug into a simpler +form. For example, consider client code that parses some source file +into some internal representation, and then walks this IR, calling into +libgccjit. If this encounters a bug, a call to +@cite{gcc_jit_context_dump_reproducer_to_file} will write out C code for +a much simpler executable that performs the equivalent calls into +libgccjit, without needing the client code and its data. + +Typically you need to supply @code{-Wno-unused-variable} when +compiling the generated file (since the result of each API call is +assigned to a unique variable within the generated C source, and not +all are necessarily then used). +@end deffn + @geindex gcc_jit_context_enable_dump (C function) -@anchor{topics/contexts gcc_jit_context_enable_dump}@anchor{56} +@anchor{topics/contexts gcc_jit_context_enable_dump}@anchor{57} @deffn {C Function} void gcc_jit_context_enable_dump (gcc_jit_context@w{ }*ctxt, const char@w{ }*dumpname, char@w{ }**out_ptr) Enable the dumping of a specific set of internal state from the @@ -4331,7 +4356,7 @@ It exists primarily for writing the library's own test suite. @end deffn @node Options<2>,,Debugging,Compilation contexts -@anchor{topics/contexts options}@anchor{57} +@anchor{topics/contexts options}@anchor{58} @subsection Options @@ -4343,25 +4368,25 @@ It exists primarily for writing the library's own test suite. @end menu @node String Options,Boolean options,,Options<2> -@anchor{topics/contexts string-options}@anchor{58} +@anchor{topics/contexts string-options}@anchor{59} @subsubsection String Options @geindex gcc_jit_context_set_str_option (C function) -@anchor{topics/contexts gcc_jit_context_set_str_option}@anchor{59} +@anchor{topics/contexts gcc_jit_context_set_str_option}@anchor{5a} @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) Set a string option of the context. @geindex gcc_jit_str_option (C type) -@anchor{topics/contexts gcc_jit_str_option}@anchor{5a} +@anchor{topics/contexts gcc_jit_str_option}@anchor{5b} @deffn {C Type} enum gcc_jit_str_option @end deffn There is currently just one string option: @geindex GCC_JIT_STR_OPTION_PROGNAME (C macro) -@anchor{topics/contexts GCC_JIT_STR_OPTION_PROGNAME}@anchor{5b} +@anchor{topics/contexts GCC_JIT_STR_OPTION_PROGNAME}@anchor{5c} @deffn {C Macro} GCC_JIT_STR_OPTION_PROGNAME The name of the program, for use as a prefix when printing error @@ -4370,7 +4395,7 @@ messages to stderr. If @cite{NULL}, or default, "libgccjit.so" is used. @end deffn @node Boolean options,Integer options,String Options,Options<2> -@anchor{topics/contexts boolean-options}@anchor{5c} +@anchor{topics/contexts boolean-options}@anchor{5d} @subsubsection Boolean options @@ -4382,7 +4407,7 @@ Set a boolean option of the context. Zero is "false" (the default), non-zero is "true". @geindex gcc_jit_bool_option (C type) -@anchor{topics/contexts gcc_jit_bool_option}@anchor{5d} +@anchor{topics/contexts gcc_jit_bool_option}@anchor{5e} @deffn {C Type} enum gcc_jit_bool_option @end deffn @@ -4400,7 +4425,7 @@ location information for the code (by creating and passing in @end deffn @geindex GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE (C macro) -@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE}@anchor{5e} +@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE}@anchor{5f} @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE If true, @pxref{15,,gcc_jit_context_compile()} will dump its initial @@ -4497,7 +4522,7 @@ square: @end deffn @geindex GCC_JIT_BOOL_OPTION_DUMP_SUMMARY (C macro) -@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_SUMMARY}@anchor{5f} +@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_SUMMARY}@anchor{60} @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_SUMMARY If true, @pxref{15,,gcc_jit_context_compile()} will print information to stderr @@ -4506,19 +4531,19 @@ the time taken and memory usage of each phase. @end deffn @geindex GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING (C macro) -@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING}@anchor{60} +@anchor{topics/contexts GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING}@anchor{61} @deffn {C Macro} GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING If true, @pxref{15,,gcc_jit_context_compile()} will dump copious amount of information on what it's doing to various files within a temporary directory. Use -@pxref{61,,GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES} (see below) to +@pxref{62,,GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES} (see below) to see the results. The files are intended to be human-readable, but the exact files and their formats are subject to change. @end deffn @geindex GCC_JIT_BOOL_OPTION_SELFCHECK_GC (C macro) -@anchor{topics/contexts GCC_JIT_BOOL_OPTION_SELFCHECK_GC}@anchor{62} +@anchor{topics/contexts GCC_JIT_BOOL_OPTION_SELFCHECK_GC}@anchor{63} @deffn {C Macro} GCC_JIT_BOOL_OPTION_SELFCHECK_GC If true, libgccjit will aggressively run its garbage collector, to @@ -4528,7 +4553,7 @@ used when running the selftest suite. @end deffn @geindex GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (C macro) -@anchor{topics/contexts GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES}@anchor{61} +@anchor{topics/contexts GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES}@anchor{62} @deffn {C Macro} GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES If true, the @pxref{8,,gcc_jit_context} will not clean up intermediate files @@ -4537,7 +4562,7 @@ written to the filesystem, and will display their location on stderr. @end deffn @node Integer options,,Boolean options,Options<2> -@anchor{topics/contexts integer-options}@anchor{63} +@anchor{topics/contexts integer-options}@anchor{64} @subsubsection Integer options @@ -4548,7 +4573,7 @@ written to the filesystem, and will display their location on stderr. Set an integer option of the context. @geindex gcc_jit_int_option (C type) -@anchor{topics/contexts gcc_jit_int_option}@anchor{64} +@anchor{topics/contexts gcc_jit_int_option}@anchor{65} @deffn {C Type} enum gcc_jit_int_option @end deffn @@ -4585,7 +4610,7 @@ The default value is 0 (unoptimized). @c . @node Objects,Types,Compilation contexts,Topic Reference -@anchor{topics/objects objects}@anchor{65}@anchor{topics/objects doc}@anchor{66} +@anchor{topics/objects objects}@anchor{66}@anchor{topics/objects doc}@anchor{67} @section Objects @@ -4645,7 +4670,7 @@ gcc_jit_object *obj = gcc_jit_type_as_object (int_type); The object "base class" has the following operations: @geindex gcc_jit_object_get_context (C function) -@anchor{topics/objects gcc_jit_object_get_context}@anchor{67} +@anchor{topics/objects gcc_jit_object_get_context}@anchor{68} @deffn {C Function} gcc_jit_context *gcc_jit_object_get_context (gcc_jit_object@w{ }*obj) Which context is "obj" within? @@ -4701,7 +4726,7 @@ object's context is released. @c . @node Types,Expressions,Objects,Topic Reference -@anchor{topics/types doc}@anchor{68}@anchor{topics/types types}@anchor{69} +@anchor{topics/types doc}@anchor{69}@anchor{topics/types types}@anchor{6a} @section Types @@ -4738,7 +4763,7 @@ See @pxref{b,,gcc_jit_context_get_type()} for the available types. @item derived types can be accessed by using functions such as -@pxref{6a,,gcc_jit_type_get_pointer()} and @pxref{6b,,gcc_jit_type_get_const()}: +@pxref{6b,,gcc_jit_type_get_pointer()} and @pxref{6c,,gcc_jit_type_get_const()}: @example gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type)); @@ -4759,7 +4784,7 @@ by creating structures (see below). @end menu @node Standard types,Pointers const and volatile,,Types -@anchor{topics/types standard-types}@anchor{6c} +@anchor{topics/types standard-types}@anchor{6d} @subsection Standard types @@ -4964,66 +4989,66 @@ C99's @code{_Complex long double} @end deffn @geindex gcc_jit_context_get_int_type (C function) -@anchor{topics/types gcc_jit_context_get_int_type}@anchor{6d} +@anchor{topics/types gcc_jit_context_get_int_type}@anchor{6e} @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) Access the integer type of the given size. @end deffn @node Pointers const and volatile,Structures and unions,Standard types,Types -@anchor{topics/types pointers-const-and-volatile}@anchor{6e} +@anchor{topics/types pointers-const-and-volatile}@anchor{6f} @subsection Pointers, @cite{const}, and @cite{volatile} @geindex gcc_jit_type_get_pointer (C function) -@anchor{topics/types gcc_jit_type_get_pointer}@anchor{6a} +@anchor{topics/types gcc_jit_type_get_pointer}@anchor{6b} @deffn {C Function} gcc_jit_type *gcc_jit_type_get_pointer (gcc_jit_type@w{ }*type) Given type "T", get type "T*". @end deffn @geindex gcc_jit_type_get_const (C function) -@anchor{topics/types gcc_jit_type_get_const}@anchor{6b} +@anchor{topics/types gcc_jit_type_get_const}@anchor{6c} @deffn {C Function} gcc_jit_type *gcc_jit_type_get_const (gcc_jit_type@w{ }*type) Given type "T", get type "const T". @end deffn @geindex gcc_jit_type_get_volatile (C function) -@anchor{topics/types gcc_jit_type_get_volatile}@anchor{6f} +@anchor{topics/types gcc_jit_type_get_volatile}@anchor{70} @deffn {C Function} gcc_jit_type *gcc_jit_type_get_volatile (gcc_jit_type@w{ }*type) Given type "T", get type "volatile T". @end deffn @geindex gcc_jit_context_new_array_type (C function) -@anchor{topics/types gcc_jit_context_new_array_type}@anchor{70} +@anchor{topics/types gcc_jit_context_new_array_type}@anchor{71} @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) Given type "T", get type "T[N]" (for a constant N). @end deffn @node Structures and unions,,Pointers const and volatile,Types -@anchor{topics/types structures-and-unions}@anchor{71} +@anchor{topics/types structures-and-unions}@anchor{72} @subsection Structures and unions @geindex gcc_jit_struct (C type) -@anchor{topics/types gcc_jit_struct}@anchor{72} +@anchor{topics/types gcc_jit_struct}@anchor{73} @deffn {C Type} gcc_jit_struct @end deffn A compound type analagous to a C @cite{struct}. @geindex gcc_jit_field (C type) -@anchor{topics/types gcc_jit_field}@anchor{73} +@anchor{topics/types gcc_jit_field}@anchor{74} @deffn {C Type} gcc_jit_field @end deffn -A field within a @pxref{72,,gcc_jit_struct}. +A field within a @pxref{73,,gcc_jit_struct}. -You can model C @cite{struct} types by creating @pxref{72,,gcc_jit_struct *} and -@pxref{73,,gcc_jit_field} instances, in either order: +You can model C @cite{struct} types by creating @pxref{73,,gcc_jit_struct *} and +@pxref{74,,gcc_jit_field} instances, in either order: @itemize * @@ -5080,21 +5105,21 @@ gcc_jit_struct_set_fields (node, NULL, 2, fields); @end itemize @geindex gcc_jit_context_new_field (C function) -@anchor{topics/types gcc_jit_context_new_field}@anchor{74} +@anchor{topics/types gcc_jit_context_new_field}@anchor{75} @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) Construct a new field, with the given type and name. @end deffn @geindex gcc_jit_field_as_object (C function) -@anchor{topics/types gcc_jit_field_as_object}@anchor{75} +@anchor{topics/types gcc_jit_field_as_object}@anchor{76} @deffn {C Function} gcc_jit_object * gcc_jit_field_as_object (gcc_jit_field@w{ }*field) Upcast from field to object. @end deffn @geindex gcc_jit_context_new_struct_type (C function) -@anchor{topics/types gcc_jit_context_new_struct_type}@anchor{76} +@anchor{topics/types gcc_jit_context_new_struct_type}@anchor{77} @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) @quotation @@ -5104,24 +5129,24 @@ Construct a new struct type, with the given name and fields. @end deffn @geindex gcc_jit_context_new_opaque_struct (C function) -@anchor{topics/types gcc_jit_context_new_opaque_struct}@anchor{77} +@anchor{topics/types gcc_jit_context_new_opaque_struct}@anchor{78} @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) Construct a new struct type, with the given name, but without specifying the fields. The fields can be omitted (in which case the size of the struct is not known), or later specified using -@pxref{78,,gcc_jit_struct_set_fields()}. +@pxref{79,,gcc_jit_struct_set_fields()}. @end deffn @geindex gcc_jit_struct_as_type (C function) -@anchor{topics/types gcc_jit_struct_as_type}@anchor{79} +@anchor{topics/types gcc_jit_struct_as_type}@anchor{7a} @deffn {C Function} gcc_jit_type * gcc_jit_struct_as_type (gcc_jit_struct@w{ }*struct_type) Upcast from struct to type. @end deffn @geindex gcc_jit_struct_set_fields (C function) -@anchor{topics/types gcc_jit_struct_set_fields}@anchor{78} +@anchor{topics/types gcc_jit_struct_set_fields}@anchor{79} @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) Populate the fields of a formerly-opaque struct type. @@ -5147,7 +5172,7 @@ This can only be called once on a given struct type. @c . @node Expressions,Creating and using functions,Types,Topic Reference -@anchor{topics/expressions expressions}@anchor{7a}@anchor{topics/expressions doc}@anchor{7b} +@anchor{topics/expressions expressions}@anchor{7b}@anchor{topics/expressions doc}@anchor{7c} @section Expressions @@ -5173,7 +5198,7 @@ Lvalues @node Rvalues,Lvalues,,Expressions -@anchor{topics/expressions rvalues}@anchor{7c} +@anchor{topics/expressions rvalues}@anchor{7d} @subsection Rvalues @@ -5227,7 +5252,7 @@ Every rvalue has an associated type, and the API will check to ensure that types match up correctly (otherwise the context will emit an error). @geindex gcc_jit_rvalue_get_type (C function) -@anchor{topics/expressions gcc_jit_rvalue_get_type}@anchor{7d} +@anchor{topics/expressions gcc_jit_rvalue_get_type}@anchor{7e} @deffn {C Function} gcc_jit_type *gcc_jit_rvalue_get_type (gcc_jit_rvalue@w{ }*rvalue) Get the type of this rvalue. @@ -5251,7 +5276,7 @@ Upcast the given rvalue to be an object. @end menu @node Simple expressions,Unary Operations,,Rvalues -@anchor{topics/expressions simple-expressions}@anchor{7e} +@anchor{topics/expressions simple-expressions}@anchor{7f} @subsubsection Simple expressions @@ -5264,7 +5289,7 @@ the given constant @code{int} value. @end deffn @geindex gcc_jit_context_new_rvalue_from_long (C function) -@anchor{topics/expressions gcc_jit_context_new_rvalue_from_long}@anchor{7f} +@anchor{topics/expressions gcc_jit_context_new_rvalue_from_long}@anchor{80} @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) Given a numeric type (integer or floating point), build an rvalue for @@ -5308,14 +5333,14 @@ the given constant @code{double} value. @end deffn @geindex gcc_jit_context_new_rvalue_from_ptr (C function) -@anchor{topics/expressions gcc_jit_context_new_rvalue_from_ptr}@anchor{80} +@anchor{topics/expressions gcc_jit_context_new_rvalue_from_ptr}@anchor{81} @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) Given a pointer type, build an rvalue for the given address. @end deffn @geindex gcc_jit_context_null (C function) -@anchor{topics/expressions gcc_jit_context_null}@anchor{81} +@anchor{topics/expressions gcc_jit_context_null}@anchor{82} @deffn {C Function} gcc_jit_rvalue *gcc_jit_context_null (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type) Given a pointer type, build an rvalue for @code{NULL}. Essentially this @@ -5329,7 +5354,7 @@ gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL) @end deffn @geindex gcc_jit_context_new_string_literal (C function) -@anchor{topics/expressions gcc_jit_context_new_string_literal}@anchor{82} +@anchor{topics/expressions gcc_jit_context_new_string_literal}@anchor{83} @deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context@w{ }*ctxt, const char@w{ }*value) Generate an rvalue for the given NIL-terminated string, of type @@ -5337,19 +5362,19 @@ Generate an rvalue for the given NIL-terminated string, of type @end deffn @node Unary Operations,Binary Operations,Simple expressions,Rvalues -@anchor{topics/expressions unary-operations}@anchor{83} +@anchor{topics/expressions unary-operations}@anchor{84} @subsubsection Unary Operations @geindex gcc_jit_context_new_unary_op (C function) -@anchor{topics/expressions gcc_jit_context_new_unary_op}@anchor{84} +@anchor{topics/expressions gcc_jit_context_new_unary_op}@anchor{85} @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) Build a unary operation out of an input rvalue. @end deffn @geindex gcc_jit_unary_op (C type) -@anchor{topics/expressions gcc_jit_unary_op}@anchor{85} +@anchor{topics/expressions gcc_jit_unary_op}@anchor{86} @deffn {C Type} enum gcc_jit_unary_op @end deffn @@ -5367,7 +5392,7 @@ C equivalent @item -@pxref{86,,GCC_JIT_UNARY_OP_MINUS} +@pxref{87,,GCC_JIT_UNARY_OP_MINUS} @tab @@ -5375,7 +5400,7 @@ C equivalent @item -@pxref{87,,GCC_JIT_UNARY_OP_BITWISE_NEGATE} +@pxref{88,,GCC_JIT_UNARY_OP_BITWISE_NEGATE} @tab @@ -5383,7 +5408,7 @@ C equivalent @item -@pxref{88,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE} +@pxref{89,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE} @tab @@ -5391,7 +5416,7 @@ C equivalent @item -@pxref{89,,GCC_JIT_UNARY_OP_ABS} +@pxref{8a,,GCC_JIT_UNARY_OP_ABS} @tab @@ -5401,7 +5426,7 @@ C equivalent @geindex GCC_JIT_UNARY_OP_MINUS (C macro) -@anchor{topics/expressions GCC_JIT_UNARY_OP_MINUS}@anchor{86} +@anchor{topics/expressions GCC_JIT_UNARY_OP_MINUS}@anchor{87} @deffn {C Macro} GCC_JIT_UNARY_OP_MINUS Negate an arithmetic value; analogous to: @@ -5416,7 +5441,7 @@ in C. @end deffn @geindex GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro) -@anchor{topics/expressions GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{87} +@anchor{topics/expressions GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{88} @deffn {C Macro} GCC_JIT_UNARY_OP_BITWISE_NEGATE Bitwise negation of an integer value (one's complement); analogous @@ -5432,7 +5457,7 @@ in C. @end deffn @geindex GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro) -@anchor{topics/expressions GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{88} +@anchor{topics/expressions GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{89} @deffn {C Macro} GCC_JIT_UNARY_OP_LOGICAL_NEGATE Logical negation of an arithmetic or pointer value; analogous to: @@ -5447,7 +5472,7 @@ in C. @end deffn @geindex GCC_JIT_UNARY_OP_ABS (C macro) -@anchor{topics/expressions GCC_JIT_UNARY_OP_ABS}@anchor{89} +@anchor{topics/expressions GCC_JIT_UNARY_OP_ABS}@anchor{8a} @deffn {C Macro} GCC_JIT_UNARY_OP_ABS Absolute value of an arithmetic expression; analogous to: @@ -5462,7 +5487,7 @@ in C. @end deffn @node Binary Operations,Comparisons,Unary Operations,Rvalues -@anchor{topics/expressions binary-operations}@anchor{8a} +@anchor{topics/expressions binary-operations}@anchor{8b} @subsubsection Binary Operations @@ -5474,7 +5499,7 @@ Build a binary operation out of two constituent rvalues. @end deffn @geindex gcc_jit_binary_op (C type) -@anchor{topics/expressions gcc_jit_binary_op}@anchor{8b} +@anchor{topics/expressions gcc_jit_binary_op}@anchor{8c} @deffn {C Type} enum gcc_jit_binary_op @end deffn @@ -5492,7 +5517,7 @@ C equivalent @item -@pxref{8c,,GCC_JIT_BINARY_OP_PLUS} +@pxref{8d,,GCC_JIT_BINARY_OP_PLUS} @tab @@ -5508,7 +5533,7 @@ C equivalent @item -@pxref{8d,,GCC_JIT_BINARY_OP_MULT} +@pxref{8e,,GCC_JIT_BINARY_OP_MULT} @tab @@ -5516,7 +5541,7 @@ C equivalent @item -@pxref{8e,,GCC_JIT_BINARY_OP_DIVIDE} +@pxref{8f,,GCC_JIT_BINARY_OP_DIVIDE} @tab @@ -5524,7 +5549,7 @@ C equivalent @item -@pxref{8f,,GCC_JIT_BINARY_OP_MODULO} +@pxref{90,,GCC_JIT_BINARY_OP_MODULO} @tab @@ -5532,7 +5557,7 @@ C equivalent @item -@pxref{90,,GCC_JIT_BINARY_OP_BITWISE_AND} +@pxref{91,,GCC_JIT_BINARY_OP_BITWISE_AND} @tab @@ -5540,7 +5565,7 @@ C equivalent @item -@pxref{91,,GCC_JIT_BINARY_OP_BITWISE_XOR} +@pxref{92,,GCC_JIT_BINARY_OP_BITWISE_XOR} @tab @@ -5548,7 +5573,7 @@ C equivalent @item -@pxref{92,,GCC_JIT_BINARY_OP_BITWISE_OR} +@pxref{93,,GCC_JIT_BINARY_OP_BITWISE_OR} @tab @@ -5556,7 +5581,7 @@ C equivalent @item -@pxref{93,,GCC_JIT_BINARY_OP_LOGICAL_AND} +@pxref{94,,GCC_JIT_BINARY_OP_LOGICAL_AND} @tab @@ -5564,7 +5589,7 @@ C equivalent @item -@pxref{94,,GCC_JIT_BINARY_OP_LOGICAL_OR} +@pxref{95,,GCC_JIT_BINARY_OP_LOGICAL_OR} @tab @@ -5572,7 +5597,7 @@ C equivalent @item -@pxref{95,,GCC_JIT_BINARY_OP_LSHIFT} +@pxref{96,,GCC_JIT_BINARY_OP_LSHIFT} @tab @@ -5580,7 +5605,7 @@ C equivalent @item -@pxref{96,,GCC_JIT_BINARY_OP_RSHIFT} +@pxref{97,,GCC_JIT_BINARY_OP_RSHIFT} @tab @@ -5590,7 +5615,7 @@ C equivalent @geindex GCC_JIT_BINARY_OP_PLUS (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_PLUS}@anchor{8c} +@anchor{topics/expressions GCC_JIT_BINARY_OP_PLUS}@anchor{8d} @deffn {C Macro} GCC_JIT_BINARY_OP_PLUS Addition of arithmetic values; analogous to: @@ -5603,7 +5628,7 @@ Addition of arithmetic values; analogous to: in C. -For pointer addition, use @pxref{97,,gcc_jit_context_new_array_access()}. +For pointer addition, use @pxref{98,,gcc_jit_context_new_array_access()}. @end deffn @@ -5621,7 +5646,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_MULT (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_MULT}@anchor{8d} +@anchor{topics/expressions GCC_JIT_BINARY_OP_MULT}@anchor{8e} @deffn {C Macro} GCC_JIT_BINARY_OP_MULT Multiplication of a pair of arithmetic values; analogous to: @@ -5636,7 +5661,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_DIVIDE (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_DIVIDE}@anchor{8e} +@anchor{topics/expressions GCC_JIT_BINARY_OP_DIVIDE}@anchor{8f} @deffn {C Macro} GCC_JIT_BINARY_OP_DIVIDE Quotient of division of arithmetic values; analogous to: @@ -5655,7 +5680,7 @@ a floating-point result type indicates floating-point division. @end deffn @geindex GCC_JIT_BINARY_OP_MODULO (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_MODULO}@anchor{8f} +@anchor{topics/expressions GCC_JIT_BINARY_OP_MODULO}@anchor{90} @deffn {C Macro} GCC_JIT_BINARY_OP_MODULO Remainder of division of arithmetic values; analogous to: @@ -5670,7 +5695,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_BITWISE_AND (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{90} +@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{91} @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_AND Bitwise AND; analogous to: @@ -5685,7 +5710,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_BITWISE_XOR (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{91} +@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{92} @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_XOR Bitwise exclusive OR; analogous to: @@ -5700,7 +5725,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_BITWISE_OR (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{92} +@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{93} @deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_OR Bitwise inclusive OR; analogous to: @@ -5715,7 +5740,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_LOGICAL_AND (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{93} +@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{94} @deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_AND Logical AND; analogous to: @@ -5730,7 +5755,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_LOGICAL_OR (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{94} +@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{95} @deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_OR Logical OR; analogous to: @@ -5745,7 +5770,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_LSHIFT (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_LSHIFT}@anchor{95} +@anchor{topics/expressions GCC_JIT_BINARY_OP_LSHIFT}@anchor{96} @deffn {C Macro} GCC_JIT_BINARY_OP_LSHIFT Left shift; analogous to: @@ -5760,7 +5785,7 @@ in C. @end deffn @geindex GCC_JIT_BINARY_OP_RSHIFT (C macro) -@anchor{topics/expressions GCC_JIT_BINARY_OP_RSHIFT}@anchor{96} +@anchor{topics/expressions GCC_JIT_BINARY_OP_RSHIFT}@anchor{97} @deffn {C Macro} GCC_JIT_BINARY_OP_RSHIFT Right shift; analogous to: @@ -5775,7 +5800,7 @@ in C. @end deffn @node Comparisons,Function calls,Binary Operations,Rvalues -@anchor{topics/expressions comparisons}@anchor{98} +@anchor{topics/expressions comparisons}@anchor{99} @subsubsection Comparisons @@ -5787,7 +5812,7 @@ Build a boolean rvalue out of the comparison of two other rvalues. @end deffn @geindex gcc_jit_comparison (C type) -@anchor{topics/expressions gcc_jit_comparison}@anchor{99} +@anchor{topics/expressions gcc_jit_comparison}@anchor{9a} @deffn {C Type} enum gcc_jit_comparison @end deffn @@ -5853,12 +5878,12 @@ C equivalent @node Function calls,Type-coercion,Comparisons,Rvalues -@anchor{topics/expressions function-calls}@anchor{9a} +@anchor{topics/expressions function-calls}@anchor{9b} @subsubsection Function calls @geindex gcc_jit_context_new_call (C function) -@anchor{topics/expressions gcc_jit_context_new_call}@anchor{9b} +@anchor{topics/expressions gcc_jit_context_new_call}@anchor{9c} @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) Given a function and the given table of argument rvalues, construct a @@ -5866,7 +5891,7 @@ call to the function, with the result as an rvalue. @cartouche @quotation Note -@pxref{9b,,gcc_jit_context_new_call()} merely builds a +@pxref{9c,,gcc_jit_context_new_call()} merely builds a @pxref{13,,gcc_jit_rvalue} i.e. an expression that can be evaluated, perhaps as part of a more complicated expression. The call @emph{won't} happen unless you add a statement to a function @@ -5874,7 +5899,7 @@ that evaluates the expression. For example, if you want to call a function and discard the result (or to call a function with @code{void} return type), use -@pxref{9c,,gcc_jit_block_add_eval()}: +@pxref{9d,,gcc_jit_block_add_eval()}: @example /* Add "(void)printf (arg0, arg1);". */ @@ -5893,12 +5918,12 @@ gcc_jit_block_add_eval ( @end deffn @node Type-coercion,,Function calls,Rvalues -@anchor{topics/expressions type-coercion}@anchor{9d} +@anchor{topics/expressions type-coercion}@anchor{9e} @subsubsection Type-coercion @geindex gcc_jit_context_new_cast (C function) -@anchor{topics/expressions gcc_jit_context_new_cast}@anchor{9e} +@anchor{topics/expressions gcc_jit_context_new_cast}@anchor{9f} @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) Given an rvalue of T, construct another rvalue of another type. @@ -5923,7 +5948,7 @@ P* <-> Q*, for pointer types P and Q @end deffn @node Lvalues,Working with pointers structs and unions,Rvalues,Expressions -@anchor{topics/expressions lvalues}@anchor{9f} +@anchor{topics/expressions lvalues}@anchor{a0} @subsection Lvalues @@ -5937,21 +5962,21 @@ a storage area (such as a variable). It is also usable as an rvalue, where the rvalue is computed by reading from the storage area. @geindex gcc_jit_lvalue_as_object (C function) -@anchor{topics/expressions gcc_jit_lvalue_as_object}@anchor{a0} +@anchor{topics/expressions gcc_jit_lvalue_as_object}@anchor{a1} @deffn {C Function} gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue@w{ }*lvalue) Upcast an lvalue to be an object. @end deffn @geindex gcc_jit_lvalue_as_rvalue (C function) -@anchor{topics/expressions gcc_jit_lvalue_as_rvalue}@anchor{a1} +@anchor{topics/expressions gcc_jit_lvalue_as_rvalue}@anchor{a2} @deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue@w{ }*lvalue) Upcast an lvalue to be an rvalue. @end deffn @geindex gcc_jit_lvalue_get_address (C function) -@anchor{topics/expressions gcc_jit_lvalue_get_address}@anchor{a2} +@anchor{topics/expressions gcc_jit_lvalue_get_address}@anchor{a3} @deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_get_address (gcc_jit_lvalue@w{ }*lvalue, gcc_jit_location@w{ }*loc) Take the address of an lvalue; analogous to: @@ -5971,12 +5996,12 @@ in C. @end menu @node Global variables,,,Lvalues -@anchor{topics/expressions global-variables}@anchor{a3} +@anchor{topics/expressions global-variables}@anchor{a4} @subsubsection Global variables @geindex gcc_jit_context_new_global (C function) -@anchor{topics/expressions gcc_jit_context_new_global}@anchor{a4} +@anchor{topics/expressions gcc_jit_context_new_global}@anchor{a5} @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) Add a new global variable of the given type and name to the context. @@ -5985,22 +6010,22 @@ The "kind" parameter determines the visibility of the "global" outside of the @pxref{16,,gcc_jit_result}: @geindex gcc_jit_global_kind (C type) -@anchor{topics/expressions gcc_jit_global_kind}@anchor{a5} +@anchor{topics/expressions gcc_jit_global_kind}@anchor{a6} @deffn {C Type} enum gcc_jit_global_kind @end deffn @geindex GCC_JIT_GLOBAL_EXPORTED (C macro) -@anchor{topics/expressions GCC_JIT_GLOBAL_EXPORTED}@anchor{a6} +@anchor{topics/expressions GCC_JIT_GLOBAL_EXPORTED}@anchor{a7} @deffn {C Macro} GCC_JIT_GLOBAL_EXPORTED Global is defined by the client code and is visible by name outside of this JIT context via -@pxref{a7,,gcc_jit_result_get_global()} (and this value is required for +@pxref{a8,,gcc_jit_result_get_global()} (and this value is required for the global to be accessible via that entrypoint). @end deffn @geindex GCC_JIT_GLOBAL_INTERNAL (C macro) -@anchor{topics/expressions GCC_JIT_GLOBAL_INTERNAL}@anchor{a8} +@anchor{topics/expressions GCC_JIT_GLOBAL_INTERNAL}@anchor{a9} @deffn {C Macro} GCC_JIT_GLOBAL_INTERNAL Global is defined by the client code, but is invisible @@ -6010,7 +6035,7 @@ context and within child contexts. @end deffn @geindex GCC_JIT_GLOBAL_IMPORTED (C macro) -@anchor{topics/expressions GCC_JIT_GLOBAL_IMPORTED}@anchor{a9} +@anchor{topics/expressions GCC_JIT_GLOBAL_IMPORTED}@anchor{aa} @deffn {C Macro} GCC_JIT_GLOBAL_IMPORTED Global is not defined by the client code; we're merely @@ -6020,12 +6045,12 @@ header file. @end deffn @node Working with pointers structs and unions,,Lvalues,Expressions -@anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{aa} +@anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{ab} @subsection Working with pointers, structs and unions @geindex gcc_jit_rvalue_dereference (C function) -@anchor{topics/expressions gcc_jit_rvalue_dereference}@anchor{ab} +@anchor{topics/expressions gcc_jit_rvalue_dereference}@anchor{ac} @deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference (gcc_jit_rvalue@w{ }*rvalue, gcc_jit_location@w{ }*loc) Given an rvalue of pointer type @code{T *}, dereferencing the pointer, @@ -6043,7 +6068,7 @@ in C. Field access is provided separately for both lvalues and rvalues. @geindex gcc_jit_lvalue_access_field (C function) -@anchor{topics/expressions gcc_jit_lvalue_access_field}@anchor{ac} +@anchor{topics/expressions gcc_jit_lvalue_access_field}@anchor{ad} @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) Given an lvalue of struct or union type, access the given field, @@ -6059,7 +6084,7 @@ in C. @end deffn @geindex gcc_jit_rvalue_access_field (C function) -@anchor{topics/expressions gcc_jit_rvalue_access_field}@anchor{ad} +@anchor{topics/expressions gcc_jit_rvalue_access_field}@anchor{ae} @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) Given an rvalue of struct or union type, access the given field @@ -6075,7 +6100,7 @@ in C. @end deffn @geindex gcc_jit_rvalue_dereference_field (C function) -@anchor{topics/expressions gcc_jit_rvalue_dereference_field}@anchor{ae} +@anchor{topics/expressions gcc_jit_rvalue_dereference_field}@anchor{af} @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) Given an rvalue of pointer type @code{T *} where T is of struct or union @@ -6091,7 +6116,7 @@ in C, itself equivalent to @code{(*EXPR).FIELD}. @end deffn @geindex gcc_jit_context_new_array_access (C function) -@anchor{topics/expressions gcc_jit_context_new_array_access}@anchor{97} +@anchor{topics/expressions gcc_jit_context_new_array_access}@anchor{98} @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) Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at @@ -6126,7 +6151,7 @@ in C (or, indeed, to @code{PTR + INDEX}). @c . @node Creating and using functions,Source Locations,Expressions,Topic Reference -@anchor{topics/functions doc}@anchor{af}@anchor{topics/functions creating-and-using-functions}@anchor{b0} +@anchor{topics/functions doc}@anchor{b0}@anchor{topics/functions creating-and-using-functions}@anchor{b1} @section Creating and using functions @@ -6139,7 +6164,7 @@ in C (or, indeed, to @code{PTR + INDEX}). @end menu @node Params,Functions,,Creating and using functions -@anchor{topics/functions params}@anchor{b1} +@anchor{topics/functions params}@anchor{b2} @subsection Params @@ -6162,28 +6187,28 @@ Parameters are lvalues, and thus are also rvalues (and objects), so the following upcasts are available: @geindex gcc_jit_param_as_lvalue (C function) -@anchor{topics/functions gcc_jit_param_as_lvalue}@anchor{b2} +@anchor{topics/functions gcc_jit_param_as_lvalue}@anchor{b3} @deffn {C Function} gcc_jit_lvalue * gcc_jit_param_as_lvalue (gcc_jit_param@w{ }*param) Upcasting from param to lvalue. @end deffn @geindex gcc_jit_param_as_rvalue (C function) -@anchor{topics/functions gcc_jit_param_as_rvalue}@anchor{b3} +@anchor{topics/functions gcc_jit_param_as_rvalue}@anchor{b4} @deffn {C Function} gcc_jit_rvalue * gcc_jit_param_as_rvalue (gcc_jit_param@w{ }*param) Upcasting from param to rvalue. @end deffn @geindex gcc_jit_param_as_object (C function) -@anchor{topics/functions gcc_jit_param_as_object}@anchor{b4} +@anchor{topics/functions gcc_jit_param_as_object}@anchor{b5} @deffn {C Function} gcc_jit_object * gcc_jit_param_as_object (gcc_jit_param@w{ }*param) Upcasting from param to object. @end deffn @node Functions,Blocks,Params,Creating and using functions -@anchor{topics/functions functions}@anchor{b5} +@anchor{topics/functions functions}@anchor{b6} @subsection Functions @@ -6202,7 +6227,7 @@ creating ourselves, or one that we're referencing. Create a gcc_jit_function with the given name and parameters. @geindex gcc_jit_function_kind (C type) -@anchor{topics/functions gcc_jit_function_kind}@anchor{b6} +@anchor{topics/functions gcc_jit_function_kind}@anchor{b7} @deffn {C Type} enum gcc_jit_function_kind @end deffn @@ -6212,7 +6237,7 @@ values: @quotation @geindex GCC_JIT_FUNCTION_EXPORTED (C macro) -@anchor{topics/functions GCC_JIT_FUNCTION_EXPORTED}@anchor{b7} +@anchor{topics/functions GCC_JIT_FUNCTION_EXPORTED}@anchor{b8} @deffn {C Macro} GCC_JIT_FUNCTION_EXPORTED Function is defined by the client code and visible @@ -6224,7 +6249,7 @@ for this function from a @pxref{16,,gcc_jit_result} via @end deffn @geindex GCC_JIT_FUNCTION_INTERNAL (C macro) -@anchor{topics/functions GCC_JIT_FUNCTION_INTERNAL}@anchor{b8} +@anchor{topics/functions GCC_JIT_FUNCTION_INTERNAL}@anchor{b9} @deffn {C Macro} GCC_JIT_FUNCTION_INTERNAL Function is defined by the client code, but is invisible @@ -6232,7 +6257,7 @@ outside of the JIT. Analogous to a "static" function. @end deffn @geindex GCC_JIT_FUNCTION_IMPORTED (C macro) -@anchor{topics/functions GCC_JIT_FUNCTION_IMPORTED}@anchor{b9} +@anchor{topics/functions GCC_JIT_FUNCTION_IMPORTED}@anchor{ba} @deffn {C Macro} GCC_JIT_FUNCTION_IMPORTED Function is not defined by the client code; we're merely @@ -6241,7 +6266,7 @@ header file. @end deffn @geindex GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro) -@anchor{topics/functions GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{ba} +@anchor{topics/functions GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{bb} @deffn {C Macro} GCC_JIT_FUNCTION_ALWAYS_INLINE Function is only ever inlined into other functions, and is @@ -6258,19 +6283,19 @@ same as GCC_JIT_FUNCTION_INTERNAL. @end deffn @geindex gcc_jit_context_get_builtin_function (C function) -@anchor{topics/functions gcc_jit_context_get_builtin_function}@anchor{bb} +@anchor{topics/functions gcc_jit_context_get_builtin_function}@anchor{bc} @deffn {C Function} gcc_jit_function *gcc_jit_context_get_builtin_function (gcc_jit_context@w{ }*ctxt, const char@w{ }*name) @end deffn @geindex gcc_jit_function_as_object (C function) -@anchor{topics/functions gcc_jit_function_as_object}@anchor{bc} +@anchor{topics/functions gcc_jit_function_as_object}@anchor{bd} @deffn {C Function} gcc_jit_object * gcc_jit_function_as_object (gcc_jit_function@w{ }*func) Upcasting from function to object. @end deffn @geindex gcc_jit_function_get_param (C function) -@anchor{topics/functions gcc_jit_function_get_param}@anchor{bd} +@anchor{topics/functions gcc_jit_function_get_param}@anchor{be} @deffn {C Function} gcc_jit_param * gcc_jit_function_get_param (gcc_jit_function@w{ }*func, int@w{ }index) Get the param of the given index (0-based). @@ -6292,7 +6317,7 @@ name. @end deffn @node Blocks,Statements,Functions,Creating and using functions -@anchor{topics/functions blocks}@anchor{be} +@anchor{topics/functions blocks}@anchor{bf} @subsection Blocks @@ -6315,7 +6340,7 @@ one function. @end deffn @geindex gcc_jit_function_new_block (C function) -@anchor{topics/functions gcc_jit_function_new_block}@anchor{bf} +@anchor{topics/functions gcc_jit_function_new_block}@anchor{c0} @deffn {C Function} gcc_jit_block * gcc_jit_function_new_block (gcc_jit_function@w{ }*func, const char@w{ }*name) Create a basic block of the given name. The name may be NULL, but @@ -6325,26 +6350,26 @@ messages. @end deffn @geindex gcc_jit_block_as_object (C function) -@anchor{topics/functions gcc_jit_block_as_object}@anchor{c0} +@anchor{topics/functions gcc_jit_block_as_object}@anchor{c1} @deffn {C Function} gcc_jit_object * gcc_jit_block_as_object (gcc_jit_block@w{ }*block) Upcast from block to object. @end deffn @geindex gcc_jit_block_get_function (C function) -@anchor{topics/functions gcc_jit_block_get_function}@anchor{c1} +@anchor{topics/functions gcc_jit_block_get_function}@anchor{c2} @deffn {C Function} gcc_jit_function * gcc_jit_block_get_function (gcc_jit_block@w{ }*block) Which function is this block within? @end deffn @node Statements,,Blocks,Creating and using functions -@anchor{topics/functions statements}@anchor{c2} +@anchor{topics/functions statements}@anchor{c3} @subsection Statements @geindex gcc_jit_block_add_eval (C function) -@anchor{topics/functions gcc_jit_block_add_eval}@anchor{9c} +@anchor{topics/functions gcc_jit_block_add_eval}@anchor{9d} @deffn {C Function} void gcc_jit_block_add_eval (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue) Add evaluation of an rvalue, discarding the result @@ -6412,7 +6437,7 @@ gcc_jit_block_add_assignment_op ( Add a no-op textual comment to the internal representation of the code. It will be optimized away, but will be visible in the dumps -seen via @pxref{5e,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} +seen via @pxref{5f,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} and @pxref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, and thus may be of use when debugging how your project's internal representation gets converted to the libgccjit IR. @@ -6440,7 +6465,7 @@ block, boolval, on_true, and on_false must be non-NULL. @end deffn @geindex gcc_jit_block_end_with_jump (C function) -@anchor{topics/functions gcc_jit_block_end_with_jump}@anchor{c3} +@anchor{topics/functions gcc_jit_block_end_with_jump}@anchor{c4} @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) Terminate a block by adding a jump to the given target block. @@ -6455,7 +6480,7 @@ goto target; @end deffn @geindex gcc_jit_block_end_with_return (C function) -@anchor{topics/functions gcc_jit_block_end_with_return}@anchor{c4} +@anchor{topics/functions gcc_jit_block_end_with_return}@anchor{c5} @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) Terminate a block by adding evaluation of an rvalue, returning the value. @@ -6470,7 +6495,7 @@ return expression; @end deffn @geindex gcc_jit_block_end_with_void_return (C function) -@anchor{topics/functions gcc_jit_block_end_with_void_return}@anchor{c5} +@anchor{topics/functions gcc_jit_block_end_with_void_return}@anchor{c6} @deffn {C Function} void gcc_jit_block_end_with_void_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc) Terminate a block by adding a valueless return, for use within a function @@ -6503,7 +6528,7 @@ return; @c . @node Source Locations,Compilation results,Creating and using functions,Topic Reference -@anchor{topics/locations source-locations}@anchor{c6}@anchor{topics/locations doc}@anchor{c7} +@anchor{topics/locations source-locations}@anchor{c7}@anchor{topics/locations doc}@anchor{c8} @section Source Locations @@ -6549,7 +6574,7 @@ location. @end menu @node Faking it,,,Source Locations -@anchor{topics/locations faking-it}@anchor{c8} +@anchor{topics/locations faking-it}@anchor{c9} @subsection Faking it @@ -6587,7 +6612,7 @@ file, giving you @emph{something} you can step through in the debugger. @c . @node Compilation results,,Source Locations,Topic Reference -@anchor{topics/results compilation-results}@anchor{c9}@anchor{topics/results doc}@anchor{ca} +@anchor{topics/results compilation-results}@anchor{ca}@anchor{topics/results doc}@anchor{cb} @section Compilation results @@ -6622,7 +6647,7 @@ Functions are looked up by name. For this to succeed, a function with a name matching @cite{funcname} must have been created on @cite{result}'s context (or a parent context) via a call to @pxref{11,,gcc_jit_context_new_function()} with @cite{kind} -@pxref{b7,,GCC_JIT_FUNCTION_EXPORTED}: +@pxref{b8,,GCC_JIT_FUNCTION_EXPORTED}: @example gcc_jit_context_new_function (ctxt, @@ -6652,7 +6677,7 @@ to a segmentation fault. @end deffn @geindex gcc_jit_result_get_global (C function) -@anchor{topics/results gcc_jit_result_get_global}@anchor{a7} +@anchor{topics/results gcc_jit_result_get_global}@anchor{a8} @deffn {C Function} void * gcc_jit_result_get_global (gcc_jit_result@w{ }*result, const char@w{ }*name) Locate a given global within the built machine code. @@ -6660,8 +6685,8 @@ Locate a given global within the built machine code. Globals are looked up by name. For this to succeed, a global with a name matching @cite{name} must have been created on @cite{result}'s context (or a parent context) via a call to -@pxref{a4,,gcc_jit_context_new_global()} with @cite{kind} -@pxref{a6,,GCC_JIT_GLOBAL_EXPORTED}. +@pxref{a5,,gcc_jit_context_new_global()} with @cite{kind} +@pxref{a7,,GCC_JIT_GLOBAL_EXPORTED}. If the global is found, the result will need to be cast to a pointer of the correct type before it can be called. @@ -6709,7 +6734,7 @@ Once we're done with the code, this unloads the built .so file. This cleans up the result; after calling this, it's no longer valid to use the result, or any code or globals that were obtained by calling @pxref{17,,gcc_jit_result_get_code()} or -@pxref{a7,,gcc_jit_result_get_global()} on it. +@pxref{a8,,gcc_jit_result_get_global()} on it. @end deffn @c Copyright (C) 2014 Free Software Foundation, Inc. @@ -6730,7 +6755,7 @@ by calling @pxref{17,,gcc_jit_result_get_code()} or @c . @node C++ bindings for libgccjit,Internals,Topic Reference,Top -@anchor{cp/index c-bindings-for-libgccjit}@anchor{cb}@anchor{cp/index doc}@anchor{cc} +@anchor{cp/index c-bindings-for-libgccjit}@anchor{cc}@anchor{cp/index doc}@anchor{cd} @chapter C++ bindings for libgccjit @@ -6872,7 +6897,7 @@ Source Locations @node Tutorial<2>,Topic Reference<2>,,C++ bindings for libgccjit -@anchor{cp/intro/index doc}@anchor{cd}@anchor{cp/intro/index tutorial}@anchor{ce} +@anchor{cp/intro/index doc}@anchor{ce}@anchor{cp/intro/index tutorial}@anchor{cf} @section Tutorial @@ -6902,7 +6927,7 @@ Source Locations @end menu @node Tutorial part 1 "Hello world"<2>,Tutorial part 2 Creating a trivial machine code function<2>,,Tutorial<2> -@anchor{cp/intro/tutorial01 doc}@anchor{cf}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{d0} +@anchor{cp/intro/tutorial01 doc}@anchor{d0}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{d1} @subsection Tutorial part 1: "Hello world" @@ -7072,7 +7097,7 @@ hello world @c . @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> -@anchor{cp/intro/tutorial02 doc}@anchor{d1}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{d2} +@anchor{cp/intro/tutorial02 doc}@anchor{d2}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{d3} @subsection Tutorial part 2: Creating a trivial machine code function @@ -7101,7 +7126,7 @@ All state associated with compilation is associated with a @code{gccjit::context}, which is a thin C++ wrapper around the C API's @pxref{8,,gcc_jit_context *}. -Create one using @pxref{d3,,gccjit;;context;;acquire()}: +Create one using @pxref{d4,,gccjit;;context;;acquire()}: @example gccjit::context ctxt; @@ -7114,7 +7139,7 @@ The JIT library has a system of types. It is statically-typed: every expression is of a specific type, fixed at compile-time. In our example, all of the expressions are of the C @cite{int} type, so let's obtain this from the context, as a @code{gccjit::type}, using -@pxref{d4,,gccjit;;context;;get_type()}: +@pxref{d5,,gccjit;;context;;get_type()}: @example gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); @@ -7127,7 +7152,7 @@ entity in the API is associated with a @code{gccjit::context}. Memory management is easy: all such "contextual" objects are automatically cleaned up for you when the context is released, using -@pxref{d5,,gccjit;;context;;release()}: +@pxref{d6,,gccjit;;context;;release()}: @example ctxt.release (); @@ -7160,7 +7185,7 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this: One thing you can do with a @code{gccjit::object} is to ask it for a human-readable description as a @code{std::string}, using -@pxref{d6,,gccjit;;object;;get_debug_string()}: +@pxref{d7,,gccjit;;object;;get_debug_string()}: @example printf ("obj: %s\n", obj.get_debug_string ().c_str ()); @@ -7180,7 +7205,7 @@ This is invaluable when debugging. Let's create the function. To do so, we first need to construct its single parameter, specifying its type and giving it a name, -using @pxref{d7,,gccjit;;context;;new_param()}: +using @pxref{d8,,gccjit;;context;;new_param()}: @example gccjit::param param_i = ctxt.new_param (int_type, "i"); @@ -7229,7 +7254,7 @@ gccjit::block block = func.new_block (); Our basic block is relatively simple: it immediately terminates by returning the value of an expression. -We can build the expression using @pxref{d8,,gccjit;;context;;new_binary_op()}: +We can build the expression using @pxref{d9,,gccjit;;context;;new_binary_op()}: @example gccjit::rvalue expr = @@ -7242,7 +7267,7 @@ gccjit::rvalue expr = A @code{gccjit::rvalue} is another example of a @code{gccjit::object} subclass. As before, we can print it with -@pxref{d6,,gccjit;;object;;get_debug_string()}. +@pxref{d7,,gccjit;;object;;get_debug_string()}. @example printf ("expr: %s\n", expr.get_debug_string ().c_str ()); @@ -7279,7 +7304,7 @@ block.end_with_return (expr); @noindent OK, we've populated the context. We can now compile it using -@pxref{d9,,gccjit;;context;;compile()}: +@pxref{da,,gccjit;;context;;compile()}: @example gcc_jit_result *result; @@ -7329,12 +7354,12 @@ result: 25 @end menu @node Options<3>,Full example<3>,,Tutorial part 2 Creating a trivial machine code function<2> -@anchor{cp/intro/tutorial02 options}@anchor{da} +@anchor{cp/intro/tutorial02 options}@anchor{db} @subsubsection Options To get more information on what's going on, you can set debugging flags -on the context using @pxref{db,,gccjit;;context;;set_bool_option()}. +on the context using @pxref{dc,,gccjit;;context;;set_bool_option()}. @c (I'm deliberately not mentioning @c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think @@ -7406,7 +7431,7 @@ square: By default, no optimizations are performed, the equivalent of GCC's @cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling -@pxref{dc,,gccjit;;context;;set_int_option()} with +@pxref{dd,,gccjit;;context;;set_int_option()} with @pxref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: @example @@ -7440,7 +7465,7 @@ square: Naturally this has only a small effect on such a trivial function. @node Full example<3>,,Options<3>,Tutorial part 2 Creating a trivial machine code function<2> -@anchor{cp/intro/tutorial02 full-example}@anchor{dd} +@anchor{cp/intro/tutorial02 full-example}@anchor{de} @subsubsection Full example @@ -7583,7 +7608,7 @@ result: 25 @c . @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> -@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{de}@anchor{cp/intro/tutorial03 doc}@anchor{df} +@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{df}@anchor{cp/intro/tutorial03 doc}@anchor{e0} @subsection Tutorial part 3: Loops and variables @@ -7707,7 +7732,7 @@ gccjit::function func = @end menu @node Expressions lvalues and rvalues<2>,Control flow<2>,,Tutorial part 3 Loops and variables<2> -@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{e0} +@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{e1} @subsubsection Expressions: lvalues and rvalues @@ -7780,7 +7805,7 @@ body of a function. Our new example has a new kind of expression: we have two local variables. We create them by calling -@pxref{e1,,gccjit;;function;;new_local()}, supplying a type and a name: +@pxref{e2,,gccjit;;function;;new_local()}, supplying a type and a name: @example /* Build locals: */ @@ -7806,7 +7831,7 @@ Instead, having added the local to the function, we have to separately add an assignment of @cite{0} to @cite{local_i} at the beginning of the function. @node Control flow<2>,Visualizing the control flow graph<2>,Expressions lvalues and rvalues<2>,Tutorial part 3 Loops and variables<2> -@anchor{cp/intro/tutorial03 control-flow}@anchor{e2} +@anchor{cp/intro/tutorial03 control-flow}@anchor{e3} @subsubsection Control flow @@ -7845,8 +7870,8 @@ We now populate each block with statements. The entry block @cite{b_initial} consists of initializations followed by a jump to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using -@pxref{e3,,gccjit;;block;;add_assignment()} to add -an assignment statement, and using @pxref{e4,,gccjit;;context;;zero()} to get +@pxref{e4,,gccjit;;block;;add_assignment()} to add +an assignment statement, and using @pxref{e5,,gccjit;;context;;zero()} to get the constant value @cite{0} for the relevant type for the right-hand side of the assignment: @@ -7873,7 +7898,7 @@ C example. It contains a single statement: a conditional, which jumps to one of two destination blocks depending on a boolean @code{gccjit::rvalue}, in this case the comparison of @cite{i} and @cite{n}. -We could build the comparison using @pxref{e5,,gccjit;;context;;new_comparison()}: +We could build the comparison using @pxref{e6,,gccjit;;context;;new_comparison()}: @example gccjit::rvalue guard = @@ -7884,7 +7909,7 @@ gccjit::rvalue guard = @noindent and can then use this to add @cite{b_loop_cond}'s sole statement, via -@pxref{e6,,gccjit;;block;;end_with_conditional()}: +@pxref{e7,,gccjit;;block;;end_with_conditional()}: @example b_loop_cond.end_with_conditional (guard); @@ -7916,7 +7941,7 @@ Next, we populate the body of the loop. The C statement @cite{sum += i * i;} is an assignment operation, where an lvalue is modified "in-place". We use -@pxref{e7,,gccjit;;block;;add_assignment_op()} to handle these operations: +@pxref{e8,,gccjit;;block;;add_assignment_op()} to handle these operations: @example /* sum += i * i */ @@ -7944,7 +7969,7 @@ b_loop_body.add_assignment_op (i, @cartouche @quotation Note For numeric constants other than 0 or 1, we could use -@pxref{e8,,gccjit;;context;;new_rvalue()}, which has overloads +@pxref{e9,,gccjit;;context;;new_rvalue()}, which has overloads for both @code{int} and @code{double}. @end quotation @end cartouche @@ -8020,12 +8045,12 @@ result: 285 @noindent @node Visualizing the control flow graph<2>,Full example<4>,Control flow<2>,Tutorial part 3 Loops and variables<2> -@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{e9} +@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{ea} @subsubsection Visualizing the control flow graph You can see the control flow graph of a function using -@pxref{ea,,gccjit;;function;;dump_to_dot()}: +@pxref{eb,,gccjit;;function;;dump_to_dot()}: @example func.dump_to_dot ("/tmp/sum-of-squares.dot"); @@ -8059,7 +8084,7 @@ install it with @cite{yum install python-xdot}): @end quotation @node Full example<4>,,Visualizing the control flow graph<2>,Tutorial part 3 Loops and variables<2> -@anchor{cp/intro/tutorial03 full-example}@anchor{eb} +@anchor{cp/intro/tutorial03 full-example}@anchor{ec} @subsubsection Full example @@ -8242,7 +8267,7 @@ loop_test returned: 285 @c . @node Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,,Tutorial part 3 Loops and variables<2>,Tutorial<2> -@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{ec}@anchor{cp/intro/tutorial04 doc}@anchor{ed} +@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{ed}@anchor{cp/intro/tutorial04 doc}@anchor{ee} @subsection Tutorial part 4: Adding JIT-compilation to a toy interpreter @@ -8264,7 +8289,7 @@ to it. @end menu @node Our toy interpreter<2>,Compiling to machine code<2>,,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2> -@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{ee} +@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{ef} @subsubsection Our toy interpreter @@ -8672,7 +8697,7 @@ toyvm_function::interpret (int arg, FILE *trace) @end quotation @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> -@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{ef} +@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{f0} @subsubsection Compiling to machine code @@ -8752,7 +8777,7 @@ This means our compiler has the following state: @end quotation @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> -@anchor{cp/intro/tutorial04 setting-things-up}@anchor{f0} +@anchor{cp/intro/tutorial04 setting-things-up}@anchor{f1} @subsubsection Setting things up @@ -8920,7 +8945,7 @@ We create the locals within the function. @end quotation @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> -@anchor{cp/intro/tutorial04 populating-the-function}@anchor{f1} +@anchor{cp/intro/tutorial04 populating-the-function}@anchor{f2} @subsubsection Populating the function @@ -9048,7 +9073,7 @@ stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y uninitialized. To track this kind of thing down, we can use -@pxref{f2,,gccjit;;block;;add_comment()} to add descriptive comments +@pxref{f3,,gccjit;;block;;add_comment()} to add descriptive comments to the internal representation. This is invaluable when looking through the generated IR for, say @code{factorial}: @@ -9197,14 +9222,14 @@ to the next block. This is analogous to simply incrementing the program counter. @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> -@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{f3} +@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{f4} @subsubsection Verifying the control flow graph Having finished looping over the blocks, the context is complete. As before, we can verify that the control flow and statements are sane by -using @pxref{ea,,gccjit;;function;;dump_to_dot()}: +using @pxref{eb,,gccjit;;function;;dump_to_dot()}: @example fn.dump_to_dot ("/tmp/factorial.dot"); @@ -9228,7 +9253,7 @@ errors in our compiler. @end quotation @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> -@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{f4} +@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{f5} @subsubsection Compiling the context @@ -9265,7 +9290,7 @@ We can now run the result: @end quotation @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> -@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{f5} +@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{f6} @subsubsection Single-stepping through the generated code @@ -9279,14 +9304,14 @@ It's possible to debug the generated code. To do this we need to both: @item Set up source code locations for our statements, so that we can meaningfully step through the code. We did this above by -calling @pxref{f6,,gccjit;;context;;new_location()} and using the +calling @pxref{f7,,gccjit;;context;;new_location()} and using the results. @item Enable the generation of debugging information, by setting @pxref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the @code{gccjit::context} via -@pxref{db,,gccjit;;context;;set_bool_option()}: +@pxref{dc,,gccjit;;context;;set_bool_option()}: @example ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); @@ -9358,14 +9383,14 @@ optimization level in a regular compiler. @end cartouche @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> -@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{f7} +@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{f8} @subsubsection Examining the generated code How good is the optimized code? We can turn up optimizations, by calling -@pxref{dc,,gccjit;;context;;set_int_option()} with +@pxref{dd,,gccjit;;context;;set_int_option()} with @pxref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}: @example @@ -9547,7 +9572,7 @@ Note that the stack pushing and popping have been eliminated, as has the recursive call (in favor of an iteration). @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> -@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{f8} +@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{f9} @subsubsection Putting it all together @@ -9580,7 +9605,7 @@ compiler result: 55 @noindent @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> -@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{f9} +@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{fa} @subsubsection Behind the curtain: How does our code get optimized? @@ -9781,7 +9806,7 @@ representation: @code{initial}, @code{instr4} and @code{instr9}. @end menu @node Optimizing away stack manipulation<2>,Elimination of tail recursion<2>,,Behind the curtain How does our code get optimized?<2> -@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{fa} +@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{fb} @subsubsection Optimizing away stack manipulation @@ -10061,7 +10086,7 @@ instr9: @noindent @node Elimination of tail recursion<2>,,Optimizing away stack manipulation<2>,Behind the curtain How does our code get optimized?<2> -@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{fb} +@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{fc} @subsubsection Elimination of tail recursion @@ -10148,7 +10173,7 @@ instr9: @c . @node Topic Reference<2>,,Tutorial<2>,C++ bindings for libgccjit -@anchor{cp/topics/index doc}@anchor{fc}@anchor{cp/topics/index topic-reference}@anchor{fd} +@anchor{cp/topics/index doc}@anchor{fd}@anchor{cp/topics/index topic-reference}@anchor{fe} @section Topic Reference @@ -10232,22 +10257,22 @@ Source Locations @node Compilation contexts<2>,Objects<2>,,Topic Reference<2> -@anchor{cp/topics/contexts compilation-contexts}@anchor{fe}@anchor{cp/topics/contexts doc}@anchor{ff} +@anchor{cp/topics/contexts compilation-contexts}@anchor{ff}@anchor{cp/topics/contexts doc}@anchor{100} @subsection Compilation contexts @geindex gccjit;;context (C++ class) -@anchor{cp/topics/contexts gccjit context}@anchor{100} +@anchor{cp/topics/contexts gccjit context}@anchor{101} @deffn {C++ Class} gccjit::context @end deffn -The top-level of the C++ API is the @pxref{100,,gccjit;;context} type. +The top-level of the C++ API is the @pxref{101,,gccjit;;context} type. -A @pxref{100,,gccjit;;context} instance encapsulates the state of a +A @pxref{101,,gccjit;;context} instance encapsulates the state of a compilation. You can set up options on it, and add types, functions and code. -Invoking @pxref{d9,,gccjit;;context;;compile()} on it gives you a +Invoking @pxref{da,,gccjit;;context;;compile()} on it gives you a @pxref{16,,gcc_jit_result *}. It is a thin wrapper around the C API's @pxref{8,,gcc_jit_context *}. @@ -10262,7 +10287,7 @@ It is a thin wrapper around the C API's @pxref{8,,gcc_jit_context *}. @end menu @node Lifetime-management<2>,Thread-safety<2>,,Compilation contexts<2> -@anchor{cp/topics/contexts lifetime-management}@anchor{101} +@anchor{cp/topics/contexts lifetime-management}@anchor{102} @subsubsection Lifetime-management @@ -10271,16 +10296,16 @@ have their lifetime bounded by the context they are created within, and cleanup of such objects is done for you when the context is released. @geindex gccjit;;context;;acquire (C++ function) -@anchor{cp/topics/contexts gccjit context acquire}@anchor{d3} +@anchor{cp/topics/contexts gccjit context acquire}@anchor{d4} @deffn {C++ Function} gccjit::context gccjit::context::acquire () -This function acquires a new @pxref{100,,gccjit;;context} instance, +This function acquires a new @pxref{101,,gccjit;;context} instance, which is independent of any others that may be present within this process. @end deffn @geindex gccjit;;context;;release (C++ function) -@anchor{cp/topics/contexts gccjit context release}@anchor{d5} +@anchor{cp/topics/contexts gccjit context release}@anchor{d6} @deffn {C++ Function} void gccjit::context::release () This function releases all resources associated with the given context. @@ -10299,7 +10324,7 @@ ctxt.release (); @end deffn @geindex gccjit;;context;;new_child_context (C++ function) -@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{102} +@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{103} @deffn {C++ Function} gccjit::context gccjit::context::new_child_context () Given an existing JIT context, create a child context. @@ -10331,16 +10356,16 @@ there will likely be a performance hit for such nesting. @end deffn @node Thread-safety<2>,Error-handling<3>,Lifetime-management<2>,Compilation contexts<2> -@anchor{cp/topics/contexts thread-safety}@anchor{103} +@anchor{cp/topics/contexts thread-safety}@anchor{104} @subsubsection Thread-safety -Instances of @pxref{100,,gccjit;;context} created via -@pxref{d3,,gccjit;;context;;acquire()} are independent from each other: +Instances of @pxref{101,,gccjit;;context} created via +@pxref{d4,,gccjit;;context;;acquire()} are independent from each other: only one thread may use a given context at once, but multiple threads could each have their own contexts without needing locks. -Contexts created via @pxref{102,,gccjit;;context;;new_child_context()} are +Contexts created via @pxref{103,,gccjit;;context;;new_child_context()} are related to their parent context. They can be partitioned by their ultimate ancestor into independent "family trees". Only one thread within a process may use a given "family tree" of such contexts at once, @@ -10348,7 +10373,7 @@ and if you're using multiple threads you should provide your own locking around entire such context partitions. @node Error-handling<3>,Debugging<2>,Thread-safety<2>,Compilation contexts<2> -@anchor{cp/topics/contexts error-handling}@anchor{104} +@anchor{cp/topics/contexts error-handling}@anchor{105} @subsubsection Error-handling @@ -10361,10 +10386,10 @@ NULL. You don't have to check everywhere for NULL results, since the API gracefully handles a NULL being passed in for any argument. Errors are printed on stderr and can be queried using -@pxref{105,,gccjit;;context;;get_first_error()}. +@pxref{106,,gccjit;;context;;get_first_error()}. @geindex gccjit;;context;;get_first_error (C++ function) -@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{105} +@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{106} @deffn {C++ Function} const char* gccjit::context::get_first_error (gccjit::context* ctxt) Returns the first error message that occurred on the context. @@ -10376,26 +10401,38 @@ If no errors occurred, this will be NULL. @end deffn @node Debugging<2>,Options<4>,Error-handling<3>,Compilation contexts<2> -@anchor{cp/topics/contexts debugging}@anchor{106} +@anchor{cp/topics/contexts debugging}@anchor{107} @subsubsection Debugging @geindex gccjit;;context;;dump_to_file (C++ function) -@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{107} +@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{108} @deffn {C++ Function} void gccjit::context::dump_to_file (const std::string& path, int update_locations) To help with debugging: dump a C-like representation to the given path, describing what's been set up on the context. -If "update_locations" is true, then also set up @pxref{108,,gccjit;;location} +If "update_locations" is true, then also set up @pxref{109,,gccjit;;location} information throughout the context, pointing at the dump file as if it were a source file. This may be of use in conjunction with @code{GCCJIT::BOOL_OPTION_DEBUGINFO} to allow stepping through the code in a debugger. @end deffn +@geindex gccjit;;context;;dump_reproducer_to_file (C++ function) +@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{10a} +@deffn {C++ Function} void gccjit::context::dump_reproducer_to_file (gcc_jit_context* ctxt, const char* path) + +This is a thin wrapper around the C API +@pxref{56,,gcc_jit_context_dump_reproducer_to_file()}, and hence works the +same way. + +Note that the generated source is C code, not C++; this might be of use +for seeing what the C++ bindings are doing at the C level. +@end deffn + @node Options<4>,,Debugging<2>,Compilation contexts<2> -@anchor{cp/topics/contexts options}@anchor{109} +@anchor{cp/topics/contexts options}@anchor{10b} @subsubsection Options @@ -10407,28 +10444,28 @@ code in a debugger. @end menu @node String Options<2>,Boolean options<2>,,Options<4> -@anchor{cp/topics/contexts string-options}@anchor{10a} +@anchor{cp/topics/contexts string-options}@anchor{10c} @subsubsection String Options @geindex gccjit;;context;;set_str_option (C++ function) -@anchor{cp/topics/contexts gccjit context set_str_option__enum cCP}@anchor{10b} +@anchor{cp/topics/contexts gccjit context set_str_option__enum cCP}@anchor{10d} @deffn {C++ Function} void gccjit::context::set_str_option (enum gcc_jit_str_option, const char* value) Set a string option of the context. This is a thin wrapper around the C API -@pxref{59,,gcc_jit_context_set_str_option()}; the options have the same +@pxref{5a,,gcc_jit_context_set_str_option()}; the options have the same meaning. @end deffn @node Boolean options<2>,Integer options<2>,String Options<2>,Options<4> -@anchor{cp/topics/contexts boolean-options}@anchor{10c} +@anchor{cp/topics/contexts boolean-options}@anchor{10e} @subsubsection Boolean options @geindex gccjit;;context;;set_bool_option (C++ function) -@anchor{cp/topics/contexts gccjit context set_bool_option__enum i}@anchor{db} +@anchor{cp/topics/contexts gccjit context set_bool_option__enum i}@anchor{dc} @deffn {C++ Function} void gccjit::context::set_bool_option (enum gcc_jit_bool_option, int value) Set a boolean option of the context. @@ -10439,12 +10476,12 @@ meaning. @end deffn @node Integer options<2>,,Boolean options<2>,Options<4> -@anchor{cp/topics/contexts integer-options}@anchor{10d} +@anchor{cp/topics/contexts integer-options}@anchor{10f} @subsubsection Integer options @geindex gccjit;;context;;set_int_option (C++ function) -@anchor{cp/topics/contexts gccjit context set_int_option__enum i}@anchor{dc} +@anchor{cp/topics/contexts gccjit context set_int_option__enum i}@anchor{dd} @deffn {C++ Function} void gccjit::context::set_int_option (enum gcc_jit_int_option, int value) Set an integer option of the context. @@ -10472,18 +10509,18 @@ meaning. @c . @node Objects<2>,Types<2>,Compilation contexts<2>,Topic Reference<2> -@anchor{cp/topics/objects objects}@anchor{10e}@anchor{cp/topics/objects doc}@anchor{10f} +@anchor{cp/topics/objects objects}@anchor{110}@anchor{cp/topics/objects doc}@anchor{111} @subsection Objects @geindex gccjit;;object (C++ class) -@anchor{cp/topics/objects gccjit object}@anchor{110} +@anchor{cp/topics/objects gccjit object}@anchor{112} @deffn {C++ Class} gccjit::object @end deffn Almost every entity in the API (with the exception of -@pxref{100,,gccjit;;context} and @pxref{16,,gcc_jit_result *}) is a -"contextual" object, a @pxref{110,,gccjit;;object}. +@pxref{101,,gccjit;;context} and @pxref{16,,gcc_jit_result *}) is a +"contextual" object, a @pxref{112,,gccjit;;object}. A JIT object: @@ -10493,7 +10530,7 @@ A JIT object: @itemize * @item -is associated with a @pxref{100,,gccjit;;context}. +is associated with a @pxref{101,,gccjit;;context}. @item is automatically cleaned up for you when its context is released so @@ -10519,17 +10556,17 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this: @noindent -The @pxref{110,,gccjit;;object} base class has the following operations: +The @pxref{112,,gccjit;;object} base class has the following operations: @geindex gccjit;;object;;get_context (C++ function) -@anchor{cp/topics/objects gccjit object get_contextC}@anchor{111} +@anchor{cp/topics/objects gccjit object get_contextC}@anchor{113} @deffn {C++ Function} gccjit::context gccjit::object::get_context () const Which context is the obj within? @end deffn @geindex gccjit;;object;;get_debug_string (C++ function) -@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{d6} +@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{d7} @deffn {C++ Function} std::string gccjit::object::get_debug_string () const Generate a human-readable description for the given object. @@ -10569,16 +10606,16 @@ obj: 4.0 * (float)i @c . @node Types<2>,Expressions<2>,Objects<2>,Topic Reference<2> -@anchor{cp/topics/types doc}@anchor{112}@anchor{cp/topics/types types}@anchor{113} +@anchor{cp/topics/types doc}@anchor{114}@anchor{cp/topics/types types}@anchor{115} @subsection Types @geindex gccjit;;type (C++ class) -@anchor{cp/topics/types gccjit type}@anchor{114} +@anchor{cp/topics/types gccjit type}@anchor{116} @deffn {C++ Class} gccjit::type gccjit::type represents a type within the library. It is a subclass -of @pxref{110,,gccjit;;object}. +of @pxref{112,,gccjit;;object}. @end deffn Types can be created in several ways: @@ -10588,7 +10625,7 @@ Types can be created in several ways: @item fundamental types can be accessed using -@pxref{d4,,gccjit;;context;;get_type()}: +@pxref{d5,,gccjit;;context;;get_type()}: @example gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT); @@ -10608,7 +10645,7 @@ See @pxref{b,,gcc_jit_context_get_type()} for the available types. @item derived types can be accessed by using functions such as -@pxref{115,,gccjit;;type;;get_pointer()} and @pxref{116,,gccjit;;type;;get_const()}: +@pxref{117,,gccjit;;type;;get_pointer()} and @pxref{118,,gccjit;;type;;get_const()}: @example gccjit::type const_int_star = int_type.get_const ().get_pointer (); @@ -10629,12 +10666,12 @@ by creating structures (see below). @end menu @node Standard types<2>,Pointers const and volatile<2>,,Types<2> -@anchor{cp/topics/types standard-types}@anchor{117} +@anchor{cp/topics/types standard-types}@anchor{119} @subsubsection Standard types @geindex gccjit;;context;;get_type (C++ function) -@anchor{cp/topics/types gccjit context get_type__enum}@anchor{d4} +@anchor{cp/topics/types gccjit context get_type__enum}@anchor{d5} @deffn {C++ Function} gccjit::type gccjit::context::get_type (enum gcc_jit_types) Access a specific type. This is a thin wrapper around @@ -10642,14 +10679,14 @@ Access a specific type. This is a thin wrapper around @end deffn @geindex gccjit;;context;;get_int_type (C++ function) -@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{118} +@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{11a} @deffn {C++ Function} gccjit::type gccjit::context::get_int_type (size_t num_bytes, int is_signed) Access the integer type of the given size. @end deffn @geindex gccjit;;context;;get_int_type (C++ function) -@anchor{cp/topics/types gccjit context get_int_type T}@anchor{119} +@anchor{cp/topics/types gccjit context get_int_type T}@anchor{11b} @deffn {C++ Function} gccjit::type gccjit::context::get_int_type () Access the given integer type. For example, you could map the @@ -10663,12 +10700,12 @@ gccjit::type t = ctxt.get_int_type (); @end deffn @node Pointers const and volatile<2>,Structures and unions<2>,Standard types<2>,Types<2> -@anchor{cp/topics/types pointers-const-and-volatile}@anchor{11a} +@anchor{cp/topics/types pointers-const-and-volatile}@anchor{11c} @subsubsection Pointers, @cite{const}, and @cite{volatile} @geindex gccjit;;type;;get_pointer (C++ function) -@anchor{cp/topics/types gccjit type get_pointer}@anchor{115} +@anchor{cp/topics/types gccjit type get_pointer}@anchor{117} @deffn {C++ Function} gccjit::type gccjit::type::get_pointer () Given type "T", get type "T*". @@ -10677,21 +10714,21 @@ Given type "T", get type "T*". @c FIXME: get_const doesn't seem to exist @geindex gccjit;;type;;get_const (C++ function) -@anchor{cp/topics/types gccjit type get_const}@anchor{116} +@anchor{cp/topics/types gccjit type get_const}@anchor{118} @deffn {C++ Function} gccjit::type gccjit::type::get_const () Given type "T", get type "const T". @end deffn @geindex gccjit;;type;;get_volatile (C++ function) -@anchor{cp/topics/types gccjit type get_volatile}@anchor{11b} +@anchor{cp/topics/types gccjit type get_volatile}@anchor{11d} @deffn {C++ Function} gccjit::type gccjit::type::get_volatile () Given type "T", get type "volatile T". @end deffn @geindex gccjit;;context;;new_array_type (C++ function) -@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{11c} +@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{11e} @deffn {C++ Function} gccjit::type gccjit::context::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc) Given type "T", get type "T[N]" (for a constant N). @@ -10699,31 +10736,31 @@ Param "loc" is optional. @end deffn @node Structures and unions<2>,,Pointers const and volatile<2>,Types<2> -@anchor{cp/topics/types structures-and-unions}@anchor{11d} +@anchor{cp/topics/types structures-and-unions}@anchor{11f} @subsubsection Structures and unions @geindex gccjit;;struct_ (C++ class) -@anchor{cp/topics/types gccjit struct_}@anchor{11e} +@anchor{cp/topics/types gccjit struct_}@anchor{120} @deffn {C++ Class} gccjit::struct_ @end deffn A compound type analagous to a C @cite{struct}. -@pxref{11e,,gccjit;;struct_} is a subclass of @pxref{114,,gccjit;;type} (and thus -of @pxref{110,,gccjit;;object} in turn). +@pxref{120,,gccjit;;struct_} is a subclass of @pxref{116,,gccjit;;type} (and thus +of @pxref{112,,gccjit;;object} in turn). @geindex gccjit;;field (C++ class) -@anchor{cp/topics/types gccjit field}@anchor{11f} +@anchor{cp/topics/types gccjit field}@anchor{121} @deffn {C++ Class} gccjit::field @end deffn -A field within a @pxref{11e,,gccjit;;struct_}. +A field within a @pxref{120,,gccjit;;struct_}. -@pxref{11f,,gccjit;;field} is a subclass of @pxref{110,,gccjit;;object}. +@pxref{121,,gccjit;;field} is a subclass of @pxref{112,,gccjit;;object}. -You can model C @cite{struct} types by creating @pxref{11e,,gccjit;;struct_} and -@pxref{11f,,gccjit;;field} instances, in either order: +You can model C @cite{struct} types by creating @pxref{120,,gccjit;;struct_} and +@pxref{121,,gccjit;;field} instances, in either order: @itemize * @@ -10779,14 +10816,14 @@ node.set_fields (fields); @c FIXME: the above API doesn't seem to exist yet @geindex gccjit;;context;;new_field (C++ function) -@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{120} +@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{122} @deffn {C++ Function} gccjit::field gccjit::context::new_field (gccjit::type type, const char* name, gccjit::location loc) Construct a new field, with the given type and name. @end deffn @geindex gccjit;;context;;new_struct_type (C++ function) -@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{121} +@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{123} @deffn {C++ Function} gccjit::struct_ gccjit::context::new_struct_type (const std::string& name, std::vector& fields, gccjit::location loc) @quotation @@ -10796,13 +10833,13 @@ Construct a new struct type, with the given name and fields. @end deffn @geindex gccjit;;context;;new_opaque_struct (C++ function) -@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{122} +@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{124} @deffn {C++ Function} gccjit::struct_ gccjit::context::new_opaque_struct (const std::string& name, gccjit::location loc) Construct a new struct type, with the given name, but without specifying the fields. The fields can be omitted (in which case the size of the struct is not known), or later specified using -@pxref{78,,gcc_jit_struct_set_fields()}. +@pxref{79,,gcc_jit_struct_set_fields()}. @end deffn @c Copyright (C) 2014 Free Software Foundation, Inc. @@ -10823,7 +10860,7 @@ size of the struct is not known), or later specified using @c . @node Expressions<2>,Creating and using functions<2>,Types<2>,Topic Reference<2> -@anchor{cp/topics/expressions expressions}@anchor{123}@anchor{cp/topics/expressions doc}@anchor{124} +@anchor{cp/topics/expressions expressions}@anchor{125}@anchor{cp/topics/expressions doc}@anchor{126} @subsection Expressions @@ -10849,17 +10886,17 @@ Lvalues @node Rvalues<2>,Lvalues<2>,,Expressions<2> -@anchor{cp/topics/expressions rvalues}@anchor{125} +@anchor{cp/topics/expressions rvalues}@anchor{127} @subsubsection Rvalues @geindex gccjit;;rvalue (C++ class) -@anchor{cp/topics/expressions gccjit rvalue}@anchor{126} +@anchor{cp/topics/expressions gccjit rvalue}@anchor{128} @deffn {C++ Class} gccjit::rvalue @end deffn -A @pxref{126,,gccjit;;rvalue} is an expression that can be computed. It is a -subclass of @pxref{110,,gccjit;;object}, and is a thin wrapper around +A @pxref{128,,gccjit;;rvalue} is an expression that can be computed. It is a +subclass of @pxref{112,,gccjit;;object}, and is a thin wrapper around @pxref{13,,gcc_jit_rvalue *} from the C API. It can be simple, e.g.: @@ -10905,7 +10942,7 @@ Every rvalue has an associated type, and the API will check to ensure that types match up correctly (otherwise the context will emit an error). @geindex gccjit;;rvalue;;get_type (C++ function) -@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{127} +@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{129} @deffn {C++ Function} gccjit::type gccjit::rvalue::get_type () Get the type of this rvalue. @@ -10922,12 +10959,12 @@ Get the type of this rvalue. @end menu @node Simple expressions<2>,Unary Operations<2>,,Rvalues<2> -@anchor{cp/topics/expressions simple-expressions}@anchor{128} +@anchor{cp/topics/expressions simple-expressions}@anchor{12a} @subsubsection Simple expressions @geindex gccjit;;context;;new_rvalue (C++ function) -@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{e8} +@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{e9} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, int value) const Given a numeric type (integer or floating point), build an rvalue for @@ -10935,7 +10972,7 @@ the given constant @code{int} value. @end deffn @geindex gccjit;;context;;new_rvalue (C++ function) -@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{129} +@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{12b} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, long value) const Given a numeric type (integer or floating point), build an rvalue for @@ -10943,7 +10980,7 @@ the given constant @code{long} value. @end deffn @geindex gccjit;;context;;zero (C++ function) -@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{e4} +@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{e5} @deffn {C++ Function} gccjit::rvalue gccjit::context::zero (gccjit::type numeric_type) const Given a numeric type (integer or floating point), get the rvalue for @@ -10957,7 +10994,7 @@ ctxt.new_rvalue (numeric_type, 0) @end deffn @geindex gccjit;;context;;one (C++ function) -@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{12a} +@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{12c} @deffn {C++ Function} gccjit::rvalue gccjit::context::one (gccjit::type numeric_type) const Given a numeric type (integer or floating point), get the rvalue for @@ -10971,7 +11008,7 @@ ctxt.new_rvalue (numeric_type, 1) @end deffn @geindex gccjit;;context;;new_rvalue (C++ function) -@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{12b} +@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{12d} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, double value) const Given a numeric type (integer or floating point), build an rvalue for @@ -10979,14 +11016,14 @@ the given constant @code{double} value. @end deffn @geindex gccjit;;context;;new_rvalue (C++ function) -@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{12c} +@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{12e} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type pointer_type, void* value) const Given a pointer type, build an rvalue for the given address. @end deffn @geindex gccjit;;context;;new_rvalue (C++ function) -@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{12d} +@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{12f} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (const std::string& value) const Generate an rvalue of type @code{GCC_JIT_TYPE_CONST_CHAR_PTR} for @@ -10994,12 +11031,12 @@ the given string. This is akin to a string literal. @end deffn @node Unary Operations<2>,Binary Operations<2>,Simple expressions<2>,Rvalues<2> -@anchor{cp/topics/expressions unary-operations}@anchor{12e} +@anchor{cp/topics/expressions unary-operations}@anchor{130} @subsubsection Unary Operations @geindex gccjit;;context;;new_unary_op (C++ function) -@anchor{cp/topics/expressions gccjit context new_unary_op__enum gccjit type gccjit rvalue gccjit location}@anchor{12f} +@anchor{cp/topics/expressions gccjit context new_unary_op__enum gccjit type gccjit rvalue gccjit location}@anchor{131} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc) Build a unary operation out of an input rvalue. @@ -11007,7 +11044,7 @@ Build a unary operation out of an input rvalue. Parameter @code{loc} is optional. This is a thin wrapper around the C API's -@pxref{84,,gcc_jit_context_new_unary_op()} and the available unary +@pxref{85,,gcc_jit_context_new_unary_op()} and the available unary operations are documented there. @end deffn @@ -11015,7 +11052,7 @@ There are shorter ways to spell the various specific kinds of unary operation: @geindex gccjit;;context;;new_minus (C++ function) -@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{130} +@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{132} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) Negate an arithmetic value; for example: @@ -11036,7 +11073,7 @@ builds the equivalent of this C expression: @end deffn @geindex new_bitwise_negate (C++ function) -@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{131} +@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{133} @deffn {C++ Function} gccjit::rvalue new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) Bitwise negation of an integer value (one's complement); for example: @@ -11057,7 +11094,7 @@ builds the equivalent of this C expression: @end deffn @geindex new_logical_negate (C++ function) -@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{132} +@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{134} @deffn {C++ Function} gccjit::rvalue new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc) Logical negation of an arithmetic or pointer value; for example: @@ -11080,7 +11117,7 @@ builds the equivalent of this C expression: The most concise way to spell them is with overloaded operators: @geindex operator- (C++ function) -@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{133} +@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{135} @deffn {C++ Function} gccjit::rvalue operator- (gccjit::rvalue a) @example @@ -11091,7 +11128,7 @@ gccjit::rvalue negpi = -pi; @end deffn @geindex operator~ (C++ function) -@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{134} +@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{136} @deffn {C++ Function} gccjit::rvalue operator~ (gccjit::rvalue a) @example @@ -11102,7 +11139,7 @@ gccjit::rvalue mask = ~a; @end deffn @geindex operator! (C++ function) -@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{135} +@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{137} @deffn {C++ Function} gccjit::rvalue operator! (gccjit::rvalue a) @example @@ -11113,12 +11150,12 @@ gccjit::rvalue guard = !cond; @end deffn @node Binary Operations<2>,Comparisons<2>,Unary Operations<2>,Rvalues<2> -@anchor{cp/topics/expressions binary-operations}@anchor{136} +@anchor{cp/topics/expressions binary-operations}@anchor{138} @subsubsection Binary Operations @geindex gccjit;;context;;new_binary_op (C++ function) -@anchor{cp/topics/expressions gccjit context new_binary_op__enum gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{d8} +@anchor{cp/topics/expressions gccjit context new_binary_op__enum gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{d9} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) Build a binary operation out of two constituent rvalues. @@ -11134,59 +11171,59 @@ There are shorter ways to spell the various specific kinds of binary operation: @geindex gccjit;;context;;new_plus (C++ function) -@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{137} +@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{139} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_minus (C++ function) -@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{138} +@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13a} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_mult (C++ function) -@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{139} +@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13b} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_divide (C++ function) -@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13a} +@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13c} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_modulo (C++ function) -@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13b} +@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13d} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_bitwise_and (C++ function) -@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13c} +@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13e} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_bitwise_xor (C++ function) -@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13d} +@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13f} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_bitwise_or (C++ function) -@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13e} +@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{140} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_logical_and (C++ function) -@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{13f} +@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{141} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_logical_or (C++ function) -@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{140} +@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{142} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn The most concise way to spell them is with overloaded operators: @geindex operator+ (C++ function) -@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{141} +@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{143} @deffn {C++ Function} gccjit::rvalue operator+ (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11197,7 +11234,7 @@ gccjit::rvalue sum = a + b; @end deffn @geindex operator- (C++ function) -@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{142} +@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{144} @deffn {C++ Function} gccjit::rvalue operator- (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11208,7 +11245,7 @@ gccjit::rvalue diff = a - b; @end deffn @geindex operator* (C++ function) -@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{143} +@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{145} @deffn {C++ Function} gccjit::rvalue operator* (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11219,7 +11256,7 @@ gccjit::rvalue prod = a * b; @end deffn @geindex operator/ (C++ function) -@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{144} +@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{146} @deffn {C++ Function} gccjit::rvalue operator/ (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11230,7 +11267,7 @@ gccjit::rvalue result = a / b; @end deffn @geindex operator% (C++ function) -@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{145} +@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{147} @deffn {C++ Function} gccjit::rvalue operator% (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11241,7 +11278,7 @@ gccjit::rvalue mod = a % b; @end deffn @geindex operator& (C++ function) -@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{146} +@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{148} @deffn {C++ Function} gccjit::rvalue operator& (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11252,7 +11289,7 @@ gccjit::rvalue x = a & b; @end deffn @geindex operator^ (C++ function) -@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{147} +@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{149} @deffn {C++ Function} gccjit::rvalue operator^ (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11263,7 +11300,7 @@ gccjit::rvalue x = a ^ b; @end deffn @geindex operator| (C++ function) -@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{148} +@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{14a} @deffn {C++ Function} gccjit::rvalue operator| (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11274,7 +11311,7 @@ gccjit::rvalue x = a | b; @end deffn @geindex operator&& (C++ function) -@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{149} +@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{14b} @deffn {C++ Function} gccjit::rvalue operator&& (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11285,7 +11322,7 @@ gccjit::rvalue cond = a && b; @end deffn @geindex operator|| (C++ function) -@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{14a} +@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{14c} @deffn {C++ Function} gccjit::rvalue operator|| (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11308,12 +11345,12 @@ gccjit::rvalue discriminant = (b * b) - (four * a * c); @end quotation @node Comparisons<2>,Function calls<2>,Binary Operations<2>,Rvalues<2> -@anchor{cp/topics/expressions comparisons}@anchor{14b} +@anchor{cp/topics/expressions comparisons}@anchor{14d} @subsubsection Comparisons @geindex gccjit;;context;;new_comparison (C++ function) -@anchor{cp/topics/expressions gccjit context new_comparison__enum gccjit rvalue gccjit rvalue gccjit location}@anchor{e5} +@anchor{cp/topics/expressions gccjit context new_comparison__enum gccjit rvalue gccjit rvalue gccjit location}@anchor{e6} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) Build a boolean rvalue out of the comparison of two other rvalues. @@ -11329,39 +11366,39 @@ There are shorter ways to spell the various specific kinds of binary operation: @geindex gccjit;;context;;new_eq (C++ function) -@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{14c} +@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{14e} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_ne (C++ function) -@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{14d} +@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{14f} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_lt (C++ function) -@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{14e} +@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{150} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_le (C++ function) -@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{14f} +@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{151} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_gt (C++ function) -@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{150} +@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{152} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn @geindex gccjit;;context;;new_ge (C++ function) -@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{151} +@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{153} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc) @end deffn The most concise way to spell them is with overloaded operators: @geindex operator== (C++ function) -@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{152} +@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{154} @deffn {C++ Function} gccjit::rvalue operator== (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11372,7 +11409,7 @@ gccjit::rvalue cond = (a == ctxt.zero (t_int)); @end deffn @geindex operator!= (C++ function) -@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{153} +@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{155} @deffn {C++ Function} gccjit::rvalue operator!= (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11383,7 +11420,7 @@ gccjit::rvalue cond = (i != j); @end deffn @geindex operator< (C++ function) -@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{154} +@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{156} @deffn {C++ Function} gccjit::rvalue operator< (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11394,7 +11431,7 @@ gccjit::rvalue cond = i < n; @end deffn @geindex operator<= (C++ function) -@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{155} +@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{157} @deffn {C++ Function} gccjit::rvalue operator<= (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11405,7 +11442,7 @@ gccjit::rvalue cond = i <= n; @end deffn @geindex operator> (C++ function) -@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{156} +@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{158} @deffn {C++ Function} gccjit::rvalue operator> (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11416,7 +11453,7 @@ gccjit::rvalue cond = (ch > limit); @end deffn @geindex operator>= (C++ function) -@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{157} +@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{159} @deffn {C++ Function} gccjit::rvalue operator>= (gccjit::rvalue a, gccjit::rvalue b) @example @@ -11429,12 +11466,12 @@ gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100)); @c TODO: beyond this point @node Function calls<2>,Type-coercion<2>,Comparisons<2>,Rvalues<2> -@anchor{cp/topics/expressions function-calls}@anchor{158} +@anchor{cp/topics/expressions function-calls}@anchor{15a} @subsubsection Function calls @geindex gcc_jit_context_new_call (C++ function) -@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{159} +@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{15b} @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) Given a function and the given table of argument rvalues, construct a @@ -11443,14 +11480,14 @@ call to the function, with the result as an rvalue. @cartouche @quotation Note @code{gccjit::context::new_call()} merely builds a -@pxref{126,,gccjit;;rvalue} i.e. an expression that can be evaluated, +@pxref{128,,gccjit;;rvalue} i.e. an expression that can be evaluated, perhaps as part of a more complicated expression. The call @emph{won't} happen unless you add a statement to a function that evaluates the expression. For example, if you want to call a function and discard the result (or to call a function with @code{void} return type), use -@pxref{15a,,gccjit;;block;;add_eval()}: +@pxref{15c,,gccjit;;block;;add_eval()}: @example /* Add "(void)printf (arg0, arg1);". */ @@ -11463,12 +11500,12 @@ block.add_eval (ctxt.new_call (printf_func, arg0, arg1)); @end deffn @node Type-coercion<2>,,Function calls<2>,Rvalues<2> -@anchor{cp/topics/expressions type-coercion}@anchor{15b} +@anchor{cp/topics/expressions type-coercion}@anchor{15d} @subsubsection Type-coercion @geindex gccjit;;context;;new_cast (C++ function) -@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{15c} +@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{15e} @deffn {C++ Function} gccjit::rvalue gccjit::context::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc) Given an rvalue of T, construct another rvalue of another type. @@ -11493,24 +11530,24 @@ P* <-> Q*, for pointer types P and Q @end deffn @node Lvalues<2>,Working with pointers structs and unions<2>,Rvalues<2>,Expressions<2> -@anchor{cp/topics/expressions lvalues}@anchor{15d} +@anchor{cp/topics/expressions lvalues}@anchor{15f} @subsubsection Lvalues @geindex gccjit;;lvalue (C++ class) -@anchor{cp/topics/expressions gccjit lvalue}@anchor{15e} +@anchor{cp/topics/expressions gccjit lvalue}@anchor{160} @deffn {C++ Class} gccjit::lvalue @end deffn An lvalue is something that can of the @emph{left}-hand side of an assignment: a storage area (such as a variable). It is a subclass of -@pxref{126,,gccjit;;rvalue}, where the rvalue is computed by reading from the +@pxref{128,,gccjit;;rvalue}, where the rvalue is computed by reading from the storage area. It iss a thin wrapper around @pxref{24,,gcc_jit_lvalue *} from the C API. @geindex gccjit;;lvalue;;get_address (C++ function) -@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{15f} +@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{161} @deffn {C++ Function} gccjit::rvalue gccjit::lvalue::get_address (gccjit::location loc) Take the address of an lvalue; analogous to: @@ -11532,27 +11569,27 @@ Parameter "loc" is optional. @end menu @node Global variables<2>,,,Lvalues<2> -@anchor{cp/topics/expressions global-variables}@anchor{160} +@anchor{cp/topics/expressions global-variables}@anchor{162} @subsubsection Global variables @geindex gccjit;;context;;new_global (C++ function) -@anchor{cp/topics/expressions gccjit context new_global__enum gccjit type cCP gccjit location}@anchor{161} +@anchor{cp/topics/expressions gccjit context new_global__enum gccjit type cCP gccjit location}@anchor{163} @deffn {C++ Function} gccjit::lvalue gccjit::context::new_global (enum gcc_jit_global_kind, gccjit::type type, const char* name, gccjit::location loc) Add a new global variable of the given type and name to the context. -This is a thin wrapper around @pxref{a4,,gcc_jit_context_new_global()} from +This is a thin wrapper around @pxref{a5,,gcc_jit_context_new_global()} from the C API; the "kind" parameter has the same meaning as there. @end deffn @node Working with pointers structs and unions<2>,,Lvalues<2>,Expressions<2> -@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{162} +@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{164} @subsubsection Working with pointers, structs and unions @geindex gccjit;;rvalue;;dereference (C++ function) -@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{163} +@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{165} @deffn {C++ Function} gccjit::lvalue gccjit::rvalue::dereference (gccjit::location loc) Given an rvalue of pointer type @code{T *}, dereferencing the pointer, @@ -11585,7 +11622,7 @@ gccjit::lvalue content = *ptr; Field access is provided separately for both lvalues and rvalues: @geindex gccjit;;lvalue;;access_field (C++ function) -@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{164} +@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{166} @deffn {C++ Function} gccjit::lvalue gccjit::lvalue::access_field (gccjit::field field, gccjit::location loc) Given an lvalue of struct or union type, access the given field, @@ -11601,7 +11638,7 @@ in C. @end deffn @geindex gccjit;;rvalue;;access_field (C++ function) -@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{165} +@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{167} @deffn {C++ Function} gccjit::rvalue gccjit::rvalue::access_field (gccjit::field field, gccjit::location loc) Given an rvalue of struct or union type, access the given field @@ -11617,7 +11654,7 @@ in C. @end deffn @geindex gccjit;;rvalue;;dereference_field (C++ function) -@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{166} +@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{168} @deffn {C++ Function} gccjit::lvalue gccjit::rvalue::dereference_field (gccjit::field field, gccjit::location loc) Given an rvalue of pointer type @code{T *} where T is of struct or union @@ -11633,7 +11670,7 @@ in C, itself equivalent to @code{(*EXPR).FIELD}. @end deffn @geindex gccjit;;context;;new_array_access (C++ function) -@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{167} +@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{169} @deffn {C++ Function} gccjit::lvalue gccjit::context::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc) Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at @@ -11652,7 +11689,7 @@ in C (or, indeed, to @code{PTR + INDEX}). Parameter "loc" is optional. @end deffn -For array accesses where you don't need to specify a @pxref{108,,gccjit;;location}, +For array accesses where you don't need to specify a @pxref{109,,gccjit;;location}, two overloaded operators are available: @quotation @@ -11692,7 +11729,7 @@ gccjit::lvalue element = array[0]; @c . @node Creating and using functions<2>,Source Locations<2>,Expressions<2>,Topic Reference<2> -@anchor{cp/topics/functions doc}@anchor{168}@anchor{cp/topics/functions creating-and-using-functions}@anchor{169} +@anchor{cp/topics/functions doc}@anchor{16a}@anchor{cp/topics/functions creating-and-using-functions}@anchor{16b} @subsection Creating and using functions @@ -11705,36 +11742,36 @@ gccjit::lvalue element = array[0]; @end menu @node Params<2>,Functions<2>,,Creating and using functions<2> -@anchor{cp/topics/functions params}@anchor{16a} +@anchor{cp/topics/functions params}@anchor{16c} @subsubsection Params @geindex gccjit;;param (C++ class) -@anchor{cp/topics/functions gccjit param}@anchor{16b} +@anchor{cp/topics/functions gccjit param}@anchor{16d} @deffn {C++ Class} gccjit::param A @cite{gccjit::param} represents a parameter to a function. @end deffn @geindex gccjit;;context;;new_param (C++ function) -@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{d7} +@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{d8} @deffn {C++ Function} gccjit::param gccjit::context::new_param (gccjit::type type, const char* name, gccjit::location loc) In preparation for creating a function, create a new parameter of the given type and name. @end deffn -@pxref{16b,,gccjit;;param} is a subclass of @pxref{15e,,gccjit;;lvalue} (and thus -of @pxref{126,,gccjit;;rvalue} and @pxref{110,,gccjit;;object}). It is a thin +@pxref{16d,,gccjit;;param} is a subclass of @pxref{160,,gccjit;;lvalue} (and thus +of @pxref{128,,gccjit;;rvalue} and @pxref{112,,gccjit;;object}). It is a thin wrapper around the C API's @pxref{25,,gcc_jit_param *}. @node Functions<2>,Blocks<2>,Params<2>,Creating and using functions<2> -@anchor{cp/topics/functions functions}@anchor{16c} +@anchor{cp/topics/functions functions}@anchor{16e} @subsubsection Functions @geindex gccjit;;function (C++ class) -@anchor{cp/topics/functions gccjit function}@anchor{16d} +@anchor{cp/topics/functions gccjit function}@anchor{16f} @deffn {C++ Class} gccjit::function A @cite{gccjit::function} represents a function - either one that we're @@ -11752,29 +11789,29 @@ This is a wrapper around the C API's @pxref{11,,gcc_jit_context_new_function()}. @end deffn @geindex gccjit;;context;;get_builtin_function (C++ function) -@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{16e} +@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{170} @deffn {C++ Function} gccjit::function gccjit::context::get_builtin_function (const char* name) This is a wrapper around the C API's -@pxref{bb,,gcc_jit_context_get_builtin_function()}. +@pxref{bc,,gcc_jit_context_get_builtin_function()}. @end deffn @geindex gccjit;;function;;get_param (C++ function) -@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{16f} +@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{171} @deffn {C++ Function} gccjit::param gccjit::function::get_param (int index) const Get the param of the given index (0-based). @end deffn @geindex gccjit;;function;;dump_to_dot (C++ function) -@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{ea} +@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{eb} @deffn {C++ Function} void gccjit::function::dump_to_dot (const char* path) Emit the function in graphviz format to the given path. @end deffn @geindex gccjit;;function;;new_local (C++ function) -@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{e1} +@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{e2} @deffn {C++ Function} gccjit::lvalue gccjit::function::new_local (gccjit::type type, const char* name, gccjit::location loc) Create a new local variable within the function, of the given type and @@ -11782,19 +11819,19 @@ name. @end deffn @node Blocks<2>,Statements<2>,Functions<2>,Creating and using functions<2> -@anchor{cp/topics/functions blocks}@anchor{170} +@anchor{cp/topics/functions blocks}@anchor{172} @subsubsection Blocks @geindex gccjit;;block (C++ class) -@anchor{cp/topics/functions gccjit block}@anchor{171} +@anchor{cp/topics/functions gccjit block}@anchor{173} @deffn {C++ Class} gccjit::block A @cite{gccjit::block} represents a basic block within a function i.e. a sequence of statements with a single entry point and a single exit point. -@pxref{171,,gccjit;;block} is a subclass of @pxref{110,,gccjit;;object}. +@pxref{173,,gccjit;;block} is a subclass of @pxref{112,,gccjit;;object}. The first basic block that you create within a function will be the entrypoint. @@ -11807,7 +11844,7 @@ one function. @end deffn @geindex gccjit;;function;;new_block (C++ function) -@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{172} +@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{174} @deffn {C++ Function} gccjit::block gccjit::function::new_block (const char* name) Create a basic block of the given name. The name may be NULL, but @@ -11817,12 +11854,12 @@ messages. @end deffn @node Statements<2>,,Blocks<2>,Creating and using functions<2> -@anchor{cp/topics/functions statements}@anchor{173} +@anchor{cp/topics/functions statements}@anchor{175} @subsubsection Statements @geindex gccjit;;block;;add_eval (C++ function) -@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{15a} +@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{15c} @deffn {C++ Function} void gccjit::block::add_eval (gccjit::rvalue rvalue, gccjit::location loc) Add evaluation of an rvalue, discarding the result @@ -11838,7 +11875,7 @@ This is equivalent to this C code: @end deffn @geindex gccjit;;block;;add_assignment (C++ function) -@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{e3} +@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{e4} @deffn {C++ Function} void gccjit::block::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc) Add evaluation of an rvalue, assigning the result to the given @@ -11854,7 +11891,7 @@ lvalue = rvalue; @end deffn @geindex gccjit;;block;;add_assignment_op (C++ function) -@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue enum gccjit rvalue gccjit location}@anchor{e7} +@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue enum gccjit rvalue gccjit location}@anchor{e8} @deffn {C++ Function} void gccjit::block::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc) Add evaluation of an rvalue, using the result to modify an @@ -11884,12 +11921,12 @@ loop_body.add_assignment_op ( @end deffn @geindex gccjit;;block;;add_comment (C++ function) -@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{f2} +@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{f3} @deffn {C++ Function} void gccjit::block::add_comment (const char* text, gccjit::location loc) Add a no-op textual comment to the internal representation of the code. It will be optimized away, but will be visible in the dumps -seen via @pxref{5e,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} +seen via @pxref{5f,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE} and @pxref{1c,,GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE}, and thus may be of use when debugging how your project's internal representation gets converted to the libgccjit IR. @@ -11898,7 +11935,7 @@ Parameter "loc" is optional. @end deffn @geindex gccjit;;block;;end_with_conditional (C++ function) -@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{e6} +@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{e7} @deffn {C++ Function} void gccjit::block::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc) Terminate a block by adding evaluation of an rvalue, branching on the @@ -11919,7 +11956,7 @@ block, boolval, on_true, and on_false must be non-NULL. @end deffn @geindex gccjit;;block;;end_with_jump (C++ function) -@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{174} +@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{176} @deffn {C++ Function} void gccjit::block::end_with_jump (gccjit::block target, gccjit::location loc) Terminate a block by adding a jump to the given target block. @@ -11934,7 +11971,7 @@ goto target; @end deffn @geindex gccjit;;block;;end_with_return (C++ function) -@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{175} +@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{177} @deffn {C++ Function} void gccjit::block::end_with_return (gccjit::rvalue rvalue, gccjit::location loc) Terminate a block. @@ -11985,12 +12022,12 @@ return; @c . @node Source Locations<2>,Compilation results<2>,Creating and using functions<2>,Topic Reference<2> -@anchor{cp/topics/locations source-locations}@anchor{176}@anchor{cp/topics/locations doc}@anchor{177} +@anchor{cp/topics/locations source-locations}@anchor{178}@anchor{cp/topics/locations doc}@anchor{179} @subsection Source Locations @geindex gccjit;;location (C++ class) -@anchor{cp/topics/locations gccjit location}@anchor{108} +@anchor{cp/topics/locations gccjit location}@anchor{109} @deffn {C++ Class} gccjit::location A @cite{gccjit::location} encapsulates a source code location, so that @@ -12001,10 +12038,10 @@ single-step through your language. @cite{gccjit::location} instances are optional: you can always omit them from any C++ API entrypoint accepting one. -You can construct them using @pxref{f6,,gccjit;;context;;new_location()}. +You can construct them using @pxref{f7,,gccjit;;context;;new_location()}. You need to enable @pxref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the -@pxref{100,,gccjit;;context} for these locations to actually be usable by +@pxref{101,,gccjit;;context} for these locations to actually be usable by the debugger: @example @@ -12015,7 +12052,7 @@ ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); @end deffn @geindex gccjit;;context;;new_location (C++ function) -@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{f6} +@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{f7} @deffn {C++ Function} gccjit::location gccjit::context::new_location (const char* filename, int line, int column) Create a @cite{gccjit::location} instance representing the given source @@ -12028,13 +12065,13 @@ location. @end menu @node Faking it<2>,,,Source Locations<2> -@anchor{cp/topics/locations faking-it}@anchor{178} +@anchor{cp/topics/locations faking-it}@anchor{17a} @subsubsection Faking it If you don't have source code for your internal representation, but need to debug, you can generate a C-like representation of the functions in -your context using @pxref{107,,gccjit;;context;;dump_to_file()}: +your context using @pxref{108,,gccjit;;context;;dump_to_file()}: @example ctxt.dump_to_file ("/tmp/something.c", @@ -12066,27 +12103,27 @@ file, giving you @emph{something} you can step through in the debugger. @c . @node Compilation results<2>,,Source Locations<2>,Topic Reference<2> -@anchor{cp/topics/results compilation-results}@anchor{179}@anchor{cp/topics/results doc}@anchor{17a} +@anchor{cp/topics/results compilation-results}@anchor{17b}@anchor{cp/topics/results doc}@anchor{17c} @subsection Compilation results @geindex gcc_jit_result (C++ type) -@anchor{cp/topics/results gcc_jit_result}@anchor{17b} +@anchor{cp/topics/results gcc_jit_result}@anchor{17d} @deffn {C++ Type} gcc_jit_result A @cite{gcc_jit_result} encapsulates the result of compiling a context. @end deffn @geindex gccjit;;context;;compile (C++ function) -@anchor{cp/topics/results gccjit context compile}@anchor{d9} -@deffn {C++ Function} @pxref{17b,,gcc_jit_result*} gccjit::context::compile () +@anchor{cp/topics/results gccjit context compile}@anchor{da} +@deffn {C++ Function} @pxref{17d,,gcc_jit_result*} gccjit::context::compile () This calls into GCC and builds the code, returning a @cite{gcc_jit_result *}. @end deffn @geindex gcc_jit_result_get_code (C++ function) -@anchor{cp/topics/results gcc_jit_result_get_code__gcc_jit_resultP cCP}@anchor{17c} +@anchor{cp/topics/results gcc_jit_result_get_code__gcc_jit_resultP cCP}@anchor{17e} @deffn {C++ Function} void* gcc_jit_result_get_code (gcc_jit_result* result, const char* funcname) Locate a given function within the built machine code. @@ -12095,7 +12132,7 @@ correct type before it can be called. @end deffn @geindex gcc_jit_result_release (C++ function) -@anchor{cp/topics/results gcc_jit_result_release__gcc_jit_resultP}@anchor{17d} +@anchor{cp/topics/results gcc_jit_result_release__gcc_jit_resultP}@anchor{17f} @deffn {C++ Function} void gcc_jit_result_release (gcc_jit_result* result) Once we're done with the code, this unloads the built .so file. @@ -12121,7 +12158,7 @@ valid to use the result. @c . @node Internals,Indices and tables,C++ bindings for libgccjit,Top -@anchor{internals/index internals}@anchor{17e}@anchor{internals/index doc}@anchor{17f} +@anchor{internals/index internals}@anchor{180}@anchor{internals/index doc}@anchor{181} @chapter Internals @@ -12130,11 +12167,12 @@ valid to use the result. * Running the test suite:: * Environment variables:: * Overview of code structure:: +* Design notes:: @end menu @node Working on the JIT library,Running the test suite,,Internals -@anchor{internals/index working-on-the-jit-library}@anchor{180} +@anchor{internals/index working-on-the-jit-library}@anchor{182} @section Working on the JIT library @@ -12171,7 +12209,7 @@ gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), Here's what those configuration options mean: @geindex command line option; --enable-host-shared -@anchor{internals/index cmdoption--enable-host-shared}@anchor{181} +@anchor{internals/index cmdoption--enable-host-shared}@anchor{183} @deffn {Option} --enable-host-shared Configuring with this option means that the compiler is built as @@ -12180,7 +12218,7 @@ but it necessary for a shared library. @end deffn @geindex command line option; --enable-languages=jit@comma{}c++ -@anchor{internals/index cmdoption--enable-languages}@anchor{182} +@anchor{internals/index cmdoption--enable-languages}@anchor{184} @deffn {Option} --enable-languages=jit,c++ This specifies which frontends to build. The JIT library looks like @@ -12199,7 +12237,7 @@ c++: error trying to exec 'cc1plus': execvp: No such file or directory @end deffn @geindex command line option; --disable-bootstrap -@anchor{internals/index cmdoption--disable-bootstrap}@anchor{183} +@anchor{internals/index cmdoption--disable-bootstrap}@anchor{185} @deffn {Option} --disable-bootstrap For hacking on the "jit" subdirectory, performing a full @@ -12209,7 +12247,7 @@ the compiler can still bootstrap itself. @end deffn @geindex command line option; --enable-checking=release -@anchor{internals/index cmdoption--enable-checking}@anchor{184} +@anchor{internals/index cmdoption--enable-checking}@anchor{186} @deffn {Option} --enable-checking=release The compile can perform extensive self-checking as it runs, useful when @@ -12220,7 +12258,7 @@ disable this self-checking. @end deffn @node Running the test suite,Environment variables,Working on the JIT library,Internals -@anchor{internals/index running-the-test-suite}@anchor{185} +@anchor{internals/index running-the-test-suite}@anchor{187} @section Running the test suite @@ -12283,7 +12321,7 @@ and once a test has been compiled, you can debug it directly: @end menu @node Running under valgrind,,,Running the test suite -@anchor{internals/index running-under-valgrind}@anchor{186} +@anchor{internals/index running-under-valgrind}@anchor{188} @subsection Running under valgrind @@ -12331,7 +12369,7 @@ When running under valgrind, it's best to have configured gcc with various known false positives. @node Environment variables,Overview of code structure,Running the test suite,Internals -@anchor{internals/index environment-variables}@anchor{187} +@anchor{internals/index environment-variables}@anchor{189} @section Environment variables @@ -12339,7 +12377,7 @@ When running client code against a locally-built libgccjit, three environment variables need to be set up: @geindex environment variable; LD_LIBRARY_PATH -@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{188} +@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{18a} @deffn {Environment Variable} LD_LIBRARY_PATH @quotation @@ -12361,7 +12399,7 @@ libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), @end deffn @geindex environment variable; PATH -@anchor{internals/index envvar-PATH}@anchor{189} +@anchor{internals/index envvar-PATH}@anchor{18b} @deffn {Environment Variable} PATH The library uses a driver executable for converting from .s assembler @@ -12380,7 +12418,7 @@ of development. @end deffn @geindex environment variable; LIBRARY_PATH -@anchor{internals/index envvar-LIBRARY_PATH}@anchor{18a} +@anchor{internals/index envvar-LIBRARY_PATH}@anchor{18c} @deffn {Environment Variable} LIBRARY_PATH The driver executable invokes the linker, and the latter needs to locate @@ -12415,8 +12453,8 @@ hello world @noindent -@node Overview of code structure,,Environment variables,Internals -@anchor{internals/index overview-of-code-structure}@anchor{18b} +@node Overview of code structure,Design notes,Environment variables,Internals +@anchor{internals/index overview-of-code-structure}@anchor{18d} @section Overview of code structure @@ -12834,8 +12872,21 @@ JIT: gcc::jit::logger::~logger() @noindent +@node Design notes,,Overview of code structure,Internals +@anchor{internals/index design-notes}@anchor{18e} +@section Design notes + + +It should not be possible for client code to cause an internal compiler +error. If this @emph{does} happen, the root cause should be isolated (perhaps +using @pxref{56,,gcc_jit_context_dump_reproducer_to_file()}) and the cause +should be rejected via additional checking. The checking ideally should +be within the libgccjit API entrypoints in libgccjit.c, since this is as +close as possible to the error; failing that, a good place is within +@code{recording::context::validate ()} in jit-recording.c. + @node Indices and tables,Index,Internals,Top -@anchor{index indices-and-tables}@anchor{18c} +@anchor{index indices-and-tables}@anchor{18f} @unnumbered Indices and tables diff --git a/gcc/jit/docs/cp/topics/contexts.rst b/gcc/jit/docs/cp/topics/contexts.rst index 4becd51aa9d..eb54e7732af 100644 --- a/gcc/jit/docs/cp/topics/contexts.rst +++ b/gcc/jit/docs/cp/topics/contexts.rst @@ -144,6 +144,16 @@ Debugging :c:macro:`GCCJIT::BOOL_OPTION_DEBUGINFO` to allow stepping through the code in a debugger. +.. function:: void\ + gccjit::context::dump_reproducer_to_file (gcc_jit_context *ctxt,\ + const char *path) + + This is a thin wrapper around the C API + :c:func:`gcc_jit_context_dump_reproducer_to_file`, and hence works the + same way. + + Note that the generated source is C code, not C++; this might be of use + for seeing what the C++ bindings are doing at the C level. Options ------- diff --git a/gcc/jit/docs/internals/index.rst b/gcc/jit/docs/internals/index.rst index 20ac337784a..0d8d5f650f2 100644 --- a/gcc/jit/docs/internals/index.rst +++ b/gcc/jit/docs/internals/index.rst @@ -277,3 +277,13 @@ generated via this call: .. literalinclude:: test-hello-world.exe.log.txt :lines: 1- + +Design notes +------------ +It should not be possible for client code to cause an internal compiler +error. If this *does* happen, the root cause should be isolated (perhaps +using :c:func:`gcc_jit_context_dump_reproducer_to_file`) and the cause +should be rejected via additional checking. The checking ideally should +be within the libgccjit API entrypoints in libgccjit.c, since this is as +close as possible to the error; failing that, a good place is within +``recording::context::validate ()`` in jit-recording.c. diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst index 3dc313c7c93..d62217befcd 100644 --- a/gcc/jit/docs/topics/contexts.rst +++ b/gcc/jit/docs/topics/contexts.rst @@ -218,6 +218,30 @@ current state of a context to the given path, whereas :c:func:`gcc_jit_context_set_logfile` enables on-going logging of future activies on a context to the given `FILE *`. + +.. function:: void\ + gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt,\ + const char *path) + + Write C source code into `path` that can be compiled into a + self-contained executable (i.e. with libgccjit as the only dependency). + The generated code will attempt to replay the API calls that have been + made into the given context. + + This may be useful when debugging the library or client code, for + reducing a complicated recipe for reproducing a bug into a simpler + form. For example, consider client code that parses some source file + into some internal representation, and then walks this IR, calling into + libgccjit. If this encounters a bug, a call to + `gcc_jit_context_dump_reproducer_to_file` will write out C code for + a much simpler executable that performs the equivalent calls into + libgccjit, without needing the client code and its data. + + Typically you need to supply :option:`-Wno-unused-variable` when + compiling the generated file (since the result of each API call is + assigned to a unique variable within the generated C source, and not + all are necessarily then used). + .. function:: void\ gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\ const char *dumpname, \ diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index 78dc1c514da..09d63badd9c 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -168,6 +168,8 @@ public: bool update_locations); ~dump (); + recording::context &get_context () { return m_ctxt; } + void write (const char *fmt, ...) GNU_PRINTF(2, 3); diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index ec247e5a70b..76eabbdf3c7 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "pretty-print.h" +#include "hash-map.h" #include @@ -98,6 +99,9 @@ dump::write (const char *fmt, ...) m_ctxt.add_error (NULL, "error writing to dump file %s", m_filename); + /* Flush after each line, to ease debugging crashes. */ + fflush (m_file); + /* Update line/column: */ for (const char *ptr = buf; *ptr; ptr++) { @@ -119,7 +123,291 @@ dump::write (const char *fmt, ...) recording::location * dump::make_location () const { - return m_ctxt.new_location (m_filename, m_line, m_column); + return m_ctxt.new_location (m_filename, m_line, m_column, + /* We need to flag such locations as *not* + created by the user, so that + reproducer::get_identifier can cope with + them appearing *after* the memento that + refers to them. */ + false); +} + +/* A collection of allocations, all of which can be released together, to + avoid needing to track and release them individually. */ + +class allocator +{ + public: + ~allocator (); + + char * + xstrdup_printf (const char *, ...) + ATTRIBUTE_RETURNS_NONNULL + GNU_PRINTF(2, 3); + + char * + xstrdup_printf_va (const char *, va_list ap) + ATTRIBUTE_RETURNS_NONNULL + GNU_PRINTF(2, 0); + + private: + auto_vec m_buffers; +}; + +/* allocator's destructor. Call "free" on all of the allocations. */ + +allocator::~allocator () +{ + unsigned i; + void *buffer; + FOR_EACH_VEC_ELT (m_buffers, i, buffer) + free (buffer); +} + +/* Formatted printing, allocating to a buffer (or exiting the process if + the allocation fails). + + The buffer exists until the allocator is cleaned up, and is freed at + that point, so the caller doesn't need to track the result. */ + +char * +allocator::xstrdup_printf (const char *fmt, ...) +{ + char *result; + va_list ap; + va_start (ap, fmt); + result = xstrdup_printf_va (fmt, ap); + va_end (ap); + return result; +} + +/* Formatted printing, allocating to a buffer (or exiting the process if + the allocation fails). + + The buffer exists until the allocator is cleaned up, and is freed at + that point, so the caller doesn't need to track the result. */ + +char * +allocator::xstrdup_printf_va (const char *fmt, va_list ap) +{ + char *result = xvasprintf (fmt, ap); + m_buffers.safe_push (result); + return result; +} + +/* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for + implementing gcc_jit_context_dump_reproducer_to_file. */ + +class reproducer : public dump +{ + public: + reproducer (recording::context &ctxt, + const char *filename); + + void + write_params (const vec &contexts); + + void + write_args (const vec &contexts); + + const char * + make_identifier (recording::memento *m, const char *prefix); + + const char * + make_tmp_identifier (const char *prefix, recording::memento *m); + + const char * + get_identifier (recording::context *ctxt); + + const char * + get_identifier (recording::memento *m); + + const char * + get_identifier_as_rvalue (recording::rvalue *m); + + const char * + get_identifier_as_lvalue (recording::lvalue *m); + + const char * + get_identifier_as_type (recording::type *m); + + char * + xstrdup_printf (const char *, ...) + ATTRIBUTE_RETURNS_NONNULL + GNU_PRINTF(2, 3); + + private: + hash_map m_identifiers; + allocator m_allocator; +}; + +/* gcc::jit::reproducer's constructor. */ + +reproducer::reproducer (recording::context &ctxt, + const char *filename) : + dump (ctxt, filename, 0), + m_identifiers (), + m_allocator () +{ +} + +/* Write out a list of contexts as a set of parameters within a + C function declaration. */ + +void +reproducer::write_params (const vec &contexts) +{ + unsigned i; + recording::context *ctxt; + FOR_EACH_VEC_ELT (contexts, i, ctxt) + { + write ("gcc_jit_context *%s", + get_identifier (ctxt)); + if (i < contexts.length () - 1) + write (",\n" + " "); + } +} + +/* Write out a list of contexts as a set of arguments within a call + to a C function. */ + +void +reproducer::write_args (const vec &contexts) +{ + unsigned i; + recording::context *ctxt; + FOR_EACH_VEC_ELT (contexts, i, ctxt) + { + write ("%s", + get_identifier (ctxt)); + if (i < contexts.length () - 1) + write (",\n" + " "); + } +} + +/* Generate a C identifier for the given memento, associating the generated + buffer with the memento (for future calls to get_identifier et al). + + The reproducer will eventually clean up the buffer in its dtor. */ +const char * +reproducer::make_identifier (recording::memento *m, const char *prefix) +{ + char *result; + if (strlen (m->get_debug_string ()) < 100) + { + result = m_allocator.xstrdup_printf ("%s_%s_%p", + prefix, + m->get_debug_string (), + (void *) m); + for (char *p = result; *p; p++) + if (!ISALNUM (*p)) + *p = '_'; + } + else + result = m_allocator.xstrdup_printf ("%s_%p", + prefix, (void *) m); + m_identifiers.put (m, result); + return result; +} + +/* Generate a C identifier for a temporary variable. + The reproducer will eventually clean up the buffer in its dtor. */ + +const char * +reproducer::make_tmp_identifier (const char *prefix, recording::memento *m) +{ + return m_allocator.xstrdup_printf ("%s_%s", + prefix, get_identifier (m)); +} + +/* Generate a C identifier for the given context. + The reproducer will eventually clean up the buffer in its dtor. */ + +const char * +reproducer::get_identifier (recording::context *ctxt) +{ + return m_allocator.xstrdup_printf ("ctxt_%p", + (void *)ctxt); +} + +/* Locate the C identifier for the given memento, which is assumed to + have already been created via make_identifier. */ + +const char * +reproducer::get_identifier (recording::memento *m) +{ + if (!m) + return "NULL"; + + /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations, + and hence these locations appear in the context's memento list + out-of-order: they appear in the context's memento list *after* + the memento that refers to them. For this case, it's simplest to + pretend that they're NULL when writing out the code to recreate the + memento that uses them. */ + if (recording::location *loc = m->dyn_cast_location ()) + if (!loc->created_by_user ()) + return "NULL"; + + const char **slot = m_identifiers.get (m); + if (!slot) + { + get_context ().add_error (NULL, + "unable to find identifier for %p: %s", + (void *)m, + m->get_debug_string ()); + gcc_unreachable (); + } + return *slot; +} + +/* Locate the C identifier for the given rvalue, wrapping it within + a gcc_*_as_rvalue upcast if necessary. */ + +const char * +reproducer::get_identifier_as_rvalue (recording::rvalue *m) +{ + return m->access_as_rvalue (*this); +} + +/* Locate the C identifier for the given lvalue, wrapping it within + a gcc_*_as_lvalue upcast if necessary. */ + +const char * +reproducer::get_identifier_as_lvalue (recording::lvalue *m) +{ + return m->access_as_lvalue (*this); +} + +/* Locate the C identifier for the given type, wrapping it within + a gcc_*_as_type upcast if necessary. */ + +const char * +reproducer::get_identifier_as_type (recording::type *m) +{ + return m->access_as_type (*this); +} + +/* Formatted printing, allocating to a buffer (or exiting the process if + the allocation fails). + + The buffer exists until the allocator is cleaned up, and is freed at + that point, so the caller doesn't need to track the result. + + Note that we can't use ggc_printf since we're not within the compiler + proper (when within gcc_jit_context_dump_reproducer_to_file). */ + +char * +reproducer::xstrdup_printf (const char *fmt, ...) +{ + char *result; + va_list ap; + va_start (ap, fmt); + result = m_allocator.xstrdup_printf_va (fmt, ap); + va_end (ap); + return result; } /********************************************************************** @@ -170,6 +458,7 @@ recording::playback_block (recording::block *b) recording::context::context (context *parent_ctxt) : log_user (NULL), m_parent_ctxt (parent_ctxt), + m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this), m_error_count (0), m_first_error_str (NULL), m_owns_first_error_str (false), @@ -349,13 +638,15 @@ recording::context::new_string (const char *text) recording::location * recording::context::new_location (const char *filename, - int line, - int column) + int line, + int column, + bool created_by_user) { recording::location *result = new recording::location (this, - new_string (filename), - line, column); + new_string (filename), + line, column, + created_by_user); record (result); return result; } @@ -1036,6 +1327,196 @@ recording::context::dump_to_file (const char *path, bool update_locations) } } +static const char * const + str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = { + "GCC_JIT_STR_OPTION_PROGNAME" +}; + +static const char * const + int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = { + "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL" +}; + +static const char * const + bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = { + "GCC_JIT_BOOL_OPTION_DEBUGINFO", + "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE", + "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE", + "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE", + "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY", + "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING", + "GCC_JIT_BOOL_OPTION_SELFCHECK_GC", + "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES" +}; + +/* Write C source code to PATH that attempts to replay the API + calls made to this context (and its parents), for use in + minimizing test cases for libgccjit. + + Implements the post-error-checking part of + gcc_jit_context_dump_reproducer_to_file. */ + +void +recording::context::dump_reproducer_to_file (const char *path) +{ + JIT_LOG_SCOPE (get_logger ()); + reproducer r (*this, path); + + /* Generate the "ancestry" of this context, as a list. */ + auto_vec ascending_contexts; + for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt) + ascending_contexts.safe_push (ctxt); + + /* Reverse the list, giving a list of contexts from + top-most parent context down through to youngest child context. + We will use this list as the parameters of the functions in + our generated file. */ + unsigned num_ctxts = ascending_contexts.length (); + auto_vec contexts (num_ctxts); + for (unsigned i = 0; i < num_ctxts; i++) + contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]); + + /* contexts[0] should be the top-level context. */ + gcc_assert (contexts[0]); + gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]); + + /* The final element in contexts should be "this". */ + gcc_assert (contexts[contexts.length () - 1] == this); + gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt + == contexts[0]); + + r.write ("/* This code was autogenerated by" + " gcc_jit_context_dump_reproducer_to_file. */\n\n"); + r.write ("#include \n\n"); + r.write ("static void\nset_options ("); + r.write_params (contexts); + r.write (");\n\n"); + r.write ("static void\ncreate_code ("); + r.write_params (contexts); + r.write (");\n\n"); + r.write ("int\nmain (int argc, const char **argv)\n"); + r.write ("{\n"); + for (unsigned i = 0; i < num_ctxts; i++) + r.write (" gcc_jit_context *%s;\n", + r.get_identifier (contexts[i])); + r.write (" gcc_jit_result *result;\n" + "\n"); + + /* Create the contexts. + The top-level context is acquired from a clean slate, the others as + children of the prior context. */ + r.write (" %s = gcc_jit_context_acquire ();\n", + r.get_identifier (contexts[0])); + for (unsigned i = 1; i < num_ctxts; i++) + r.write (" %s = gcc_jit_context_new_child_context (%s);\n", + r.get_identifier (contexts[i]), + r.get_identifier (contexts[i - 1])); + r.write (" set_options ("); + r.write_args (contexts); + r.write (");\n"); + r.write (" create_code ("); + r.write_args (contexts); + r.write (");\n"); + + r.write (" result = gcc_jit_context_compile (%s);\n", + r.get_identifier (this)); + + for (unsigned i = num_ctxts; i > 0; i--) + r.write (" gcc_jit_context_release (%s);\n", + r.get_identifier (contexts[i - 1])); + + r.write (" gcc_jit_result_release (result);\n" + " return 0;\n" + "}\n\n"); + + /* Define (char *) variables for use in calls to + gcc_jit_context_enable_dump. */ + for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) + { + if (m_requested_dumps.length ()) + { + r.write ("/* Requested dumps for %s. */\n", + r.get_identifier (contexts[ctxt_idx])); + for (unsigned i = 0; i < m_requested_dumps.length (); i++) + r.write ("static char *dump_%p;\n", + (void *)&m_requested_dumps[i]); + r.write ("\n"); + } + } + + /* Write out values of options. */ + r.write ("static void\nset_options ("); + r.write_params (contexts); + r.write (")\n{\n"); + for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) + { + if (ctxt_idx > 0) + r.write ("\n"); + + r.write (" /* Set options for %s. */\n", + r.get_identifier (contexts[ctxt_idx])); + + r.write (" /* String options. */\n"); + for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++) + r.write (" gcc_jit_context_set_str_option (%s,\n" + " %s,\n" + " \"%s\");\n", + r.get_identifier (contexts[ctxt_idx]), + str_option_reproducer_strings[opt_idx], + m_str_options[opt_idx] ? m_str_options[opt_idx] : "NULL"); + r.write (" /* Int options. */\n"); + for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++) + r.write (" gcc_jit_context_set_int_option (%s,\n" + " %s,\n" + " %i);\n", + r.get_identifier (contexts[ctxt_idx]), + int_option_reproducer_strings[opt_idx], + m_int_options[opt_idx]); + r.write (" /* Boolean options. */\n"); + for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++) + r.write (" gcc_jit_context_set_bool_option (%s,\n" + " %s,\n" + " %i);\n", + r.get_identifier (contexts[ctxt_idx]), + bool_option_reproducer_strings[opt_idx], + m_bool_options[opt_idx]); + + if (m_requested_dumps.length ()) + { + r.write (" /* Requested dumps. */\n"); + /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */ + for (unsigned i = 0; i < m_requested_dumps.length (); i++) + { + r.write (" gcc_jit_context_enable_dump (%s,\n" + " \"%s\",\n" + " &dump_%p);\n", + r.get_identifier (contexts[ctxt_idx]), + m_requested_dumps[i].m_dumpname, + (void *)&m_requested_dumps[i]); + } + } + } + r.write ("}\n\n"); + + r.write ("static void\ncreate_code ("); + r.write_params (contexts); + r.write (")\n" + "{\n"); + for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) + { + memento *m; + int i; + if (ctxt_idx > 0) + r.write ("\n\n"); + + r.write (" /* Replay of API calls for %s. */\n", + r.get_identifier (contexts[ctxt_idx])); + FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m) + m->write_reproducer (r); + } + r.write ("}\n"); +} + /* Copy the requested dumps within this context and all ancestors into OUT. */ @@ -1182,6 +1663,14 @@ recording::string::make_debug_string () return result; } +/* Implementation of recording::memento::write_reproducer for strings. */ + +void +recording::string::write_reproducer (reproducer &) +{ + /* Empty. */ +} + /* The implementation of class gcc::jit::recording::location. */ /* Implementation of recording::memento::replay_into for locations. @@ -1211,6 +1700,23 @@ recording::location::make_debug_string () m_filename->c_str (), m_line, m_column); } +/* Implementation of recording::memento::write_reproducer for locations. */ + +void +recording::location::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "loc"); + r.write (" gcc_jit_location *%s =\n" + " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* const char *filename */\n" + " %i, /* int line */\n" + " %i);/* int column */\n", + id, + r.get_identifier (get_context ()), + m_filename->get_debug_string (), + m_line, m_column); +} + /* The implementation of class gcc::jit::recording::type. */ /* Given a type T, get the type T*. @@ -1260,6 +1766,12 @@ recording::type::get_volatile () return result; } +const char * +recording::type::access_as_type (reproducer &r) +{ + return r.get_identifier (this); +} + /* Implementation of pure virtual hook recording::type::dereference for recording::memento_of_get_type. */ @@ -1529,6 +2041,42 @@ recording::memento_of_get_type::make_debug_string () return m_ctxt->new_string (get_type_strings[m_kind]); } +static const char * const get_type_enum_strings[] = { + "GCC_JIT_TYPE_VOID", + "GCC_JIT_TYPE_VOID_PTR", + "GCC_JIT_TYPE_BOOL", + "GCC_JIT_TYPE_CHAR", + "GCC_JIT_TYPE_SIGNED_CHAR", + "GCC_JIT_TYPE_UNSIGNED_CHAR", + "GCC_JIT_TYPE_SHORT", + "GCC_JIT_TYPE_UNSIGNED_SHORT", + "GCC_JIT_TYPE_INT", + "GCC_JIT_TYPE_UNSIGNED_INT", + "GCC_JIT_TYPE_LONG", + "GCC_JIT_TYPE_UNSIGNED_LONG", + "GCC_JIT_TYPE_LONG_LONG", + "GCC_JIT_TYPE_UNSIGNED_LONG_LONG", + "GCC_JIT_TYPE_FLOAT", + "GCC_JIT_TYPE_DOUBLE", + "GCC_JIT_TYPE_LONG_DOUBLE", + "GCC_JIT_TYPE_CONST_CHAR_PTR", + "GCC_JIT_TYPE_SIZE_T", + "GCC_JIT_TYPE_FILE_PTR", + "GCC_JIT_TYPE_COMPLEX_FLOAT", + "GCC_JIT_TYPE_COMPLEX_DOUBLE", + "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE" +}; + +void +recording::memento_of_get_type::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n", + id, + r.get_identifier (get_context ()), + get_type_enum_strings[m_kind]); +} + /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */ /* Override of default implementation of @@ -1576,6 +2124,26 @@ recording::memento_of_get_pointer::make_debug_string () "%s *", m_other_type->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for get_pointer. */ + +void +recording::memento_of_get_pointer::write_reproducer (reproducer &r) +{ + /* We need to special-case function pointer types; see the notes in + recording::function_type::write_deferred_reproducer. */ + if (function_type *fn_type = m_other_type->dyn_cast_function_type ()) + { + fn_type->write_deferred_reproducer (r, this); + return; + } + + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_type_get_pointer (%s);\n", + id, + r.get_identifier_as_type (m_other_type)); +} + /* The implementation of class gcc::jit::recording::memento_of_get_const. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -1597,6 +2165,18 @@ recording::memento_of_get_const::make_debug_string () "const %s", m_other_type->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for const types. */ + +void +recording::memento_of_get_const::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_type_get_const (%s);\n", + id, + r.get_identifier_as_type (m_other_type)); +} + /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -1618,6 +2198,19 @@ recording::memento_of_get_volatile::make_debug_string () "volatile %s", m_other_type->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for volatile + types. */ + +void +recording::memento_of_get_volatile::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_type_get_volatile (%s);\n", + id, + r.get_identifier_as_type (m_other_type)); +} + /* The implementation of class gcc::jit::recording::array_type */ /* Implementation of pure virtual hook recording::type::dereference for @@ -1652,6 +2245,25 @@ recording::array_type::make_debug_string () m_num_elements); } +/* Implementation of recording::memento::write_reproducer for array + types. */ + +void +recording::array_type::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "array_type"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_context_new_array_type (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *element_type */\n" + " %i); /* int num_elements */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_element_type), + m_num_elements); +} + /* The implementation of class gcc::jit::recording::function_type */ /* Constructor for gcc::jit::recording::function_type. */ @@ -1775,6 +2387,55 @@ recording::function_type::make_debug_string_with (const char *insert) return result; } +/* Implementation of recording::memento::write_reproducer for function + types. */ + +void +recording::function_type::write_reproducer (reproducer &) +{ + /* see notes below. */ +} + +/* There's a get_pointer within context::new_function_ptr_type: + the type received by client code isn't the memento for the + function_type, but instead the result of get_pointer on it. + + Hence we can't directly write a reproducer that gives function_type. + Instead we special-case things within get_pointer, detecting this + case, calling the following function. */ + +void +recording::function_type::write_deferred_reproducer (reproducer &r, + memento *ptr_type) +{ + gcc_assert (ptr_type); + r.make_identifier (this, "function_type"); + const char *ptr_id = r.make_identifier (ptr_type, "ptr_to"); + const char *param_types_id = r.make_tmp_identifier ("params_for", this); + r.write (" gcc_jit_type *%s[%i] = {\n", + param_types_id, + m_param_types.length ()); + int i; + type *param_type; + FOR_EACH_VEC_ELT (m_param_types, i, param_type) + r.write (" %s,\n", r.get_identifier_as_type (param_type)); + r.write (" };\n"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *return_type */\n" + " %i, /* int num_params */\n" + " %s, /* gcc_jit_type **param_types */\n" + " %i); /* int is_variadic */\n", + ptr_id, + r.get_identifier (get_context ()), + "NULL", /* location is not stored */ + r.get_identifier_as_type (m_return_type), + m_param_types.length (), + param_types_id, + m_is_variadic); +} + /* The implementation of class gcc::jit::recording::field. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -1811,6 +2472,24 @@ recording::field::make_debug_string () return m_name; } +/* Implementation of recording::memento::write_reproducer for fields. */ + +void +recording::field::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "field"); + r.write(" gcc_jit_field *%s =\n" + " gcc_jit_context_new_field (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *type, */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type), + m_name->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::compound_type */ /* The constructor for gcc::jit::recording::compound_type. */ @@ -1875,6 +2554,13 @@ recording::struct_::replay_into (replayer *r) true /* is_struct */)); } +const char * +recording::struct_::access_as_type (reproducer &r) +{ + return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)", + r.get_identifier (this)); +} + /* Implementation of recording::memento::make_debug_string for structs. */ @@ -1885,6 +2571,20 @@ recording::struct_::make_debug_string () "struct %s", get_name ()->c_str ()); } +void +recording::struct_::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "struct"); + r.write (" gcc_jit_struct *%s =\n" + " gcc_jit_context_new_opaque_struct (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (get_loc ()), + get_name ()->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::union_. */ /* The constructor for gcc::jit::recording::union_. */ @@ -1918,6 +2618,35 @@ recording::union_::make_debug_string () "union %s", get_name ()->c_str ()); } +/* Implementation of recording::memento::write_reproducer for unions. */ + +void +recording::union_::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "union"); + + const char *fields_id = r.make_tmp_identifier ("fields_for", this); + r.write (" gcc_jit_field *%s[%i] = {\n", + fields_id, + get_fields ()->length ()); + for (int i = 0; i < get_fields ()->length (); i++) + r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i))); + r.write (" };\n"); + + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_context_new_union_type (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* const char *name */\n" + " %i, /* int num_fields */\n" + " %s); /* gcc_jit_field **fields */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (get_loc ()), + get_name ()->get_debug_string (), + get_fields ()->length (), + fields_id); +} + /* The implementation of class gcc::jit::recording::fields. */ /* The constructor for gcc::jit::recording::fields. */ @@ -1975,6 +2704,38 @@ recording::fields::write_to_dump (dump &d) d.write ("};\n"); } +/* Implementation of recording::memento::write_reproducer for the fields + subclass. */ + +void +recording::fields::write_reproducer (reproducer &r) +{ + if (m_struct_or_union) + if (NULL == m_struct_or_union->dyn_cast_struct ()) + /* We have a union; the fields have already been written by + union::write_reproducer. */ + return; + + const char *fields_id = r.make_identifier (this, "fields"); + r.write (" gcc_jit_field *%s[%i] = {\n", + fields_id, + m_fields.length ()); + int i; + field *field; + FOR_EACH_VEC_ELT (m_fields, i, field) + r.write (" %s,\n", r.get_identifier (field)); + r.write (" };\n"); + + r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n" + " %s, /* gcc_jit_location *loc */\n" + " %i, /* int num_fields */\n" + " %s); /* gcc_jit_field **fields */\n", + r.get_identifier (m_struct_or_union), + r.get_identifier ((memento *)NULL), + m_fields.length (), + fields_id); +} + /* Implementation of recording::memento::make_debug_string for field tables. */ @@ -2143,6 +2904,17 @@ recording::rvalue::set_scope (function *scope) } +/* Implementation of recording::rvalue::access_as_rvalue for rvalues + themselves. + Instances of rvalue don't need an upcast call. */ + +const char * +recording::rvalue::access_as_rvalue (reproducer &r) +{ + return r.get_identifier (this); +} + + /* The implementation of class gcc::jit::recording::lvalue. */ /* Create a recording::new_access_field_of_lvalue instance and add it to @@ -2161,6 +2933,26 @@ recording::lvalue::access_field (recording::location *loc, return result; } +/* Implementation of recording::rvalue::access_as_rvalue for lvalues. + Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue + upcast call. */ + +const char * +recording::lvalue::access_as_rvalue (reproducer &r) +{ + return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)", + r.get_identifier (this)); +} + +/* Implementation of recording::lvalue::access_as_lvalue for lvalues. + Instances of lvalue don't need to be upcast. */ + +const char * +recording::lvalue::access_as_lvalue (reproducer &r) +{ + return r.get_identifier (this); +} + /* Create a recording::get_address_of_lvalue instance and add it to the lvalue's context's list of mementos. @@ -2189,6 +2981,45 @@ recording::param::replay_into (replayer *r) m_name->c_str ())); } +/* Implementation of recording::rvalue::access_as_rvalue for params. + Instances of param need to be wrapped in a gcc_jit_param_as_rvalue + upcast call. */ + +const char * +recording::param::access_as_rvalue (reproducer &r) +{ + return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)", + r.get_identifier (this)); +} + +/* Implementation of recording::lvalue::access_as_lvalue for params. + Instances of param need to be wrapped in a gcc_jit_param_as_lvalue + upcast call. */ + +const char * +recording::param::access_as_lvalue (reproducer &r) +{ + return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)", + r.get_identifier (this)); +} + +/* Implementation of recording::memento::write_reproducer for params. */ + +void +recording::param::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "param"); + r.write (" gcc_jit_param *%s =\n" + " gcc_jit_context_new_param (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /*gcc_jit_type *type */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type), + m_name->get_debug_string ()); +} /* The implementation of class gcc::jit::recording::function. */ @@ -2502,6 +3333,63 @@ recording::function::make_debug_string () return m_name; } +/* A table of enum gcc_jit_function_kind values expressed in string + form. */ + +static const char * const names_of_function_kinds[] = { + "GCC_JIT_FUNCTION_EXPORTED", + "GCC_JIT_FUNCTION_INTERNAL", + "GCC_JIT_FUNCTION_IMPORTED", + "GCC_JIT_FUNCTION_ALWAYS_INLINE" +}; + +/* Implementation of recording::memento::write_reproducer for functions. */ + +void +recording::function::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "func"); + + if (m_builtin_id) + { + r.write (" gcc_jit_function *%s =\n" + " gcc_jit_context_get_builtin_function (%s,\n" + " %s);\n", + id, + r.get_identifier (get_context ()), + m_name->get_debug_string ()); + return; + } + const char *params_id = r.make_tmp_identifier ("params_for", this); + r.write (" gcc_jit_param *%s[%i] = {\n", + params_id, + m_params.length ()); + int i; + param *param; + FOR_EACH_VEC_ELT (m_params, i, param) + r.write (" %s,\n", r.get_identifier (param)); + r.write (" };\n"); + r.write (" gcc_jit_function *%s =\n" + " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* enum gcc_jit_function_kind kind */\n" + " %s, /* gcc_jit_type *return_type */\n" + " %s, /* const char *name */\n" + " %i, /* int num_params */\n" + " %s, /* gcc_jit_param **params */\n" + " %i); /* int is_variadic */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + names_of_function_kinds[m_kind], + r.get_identifier_as_type (m_return_type), + m_name->get_debug_string (), + m_params.length (), + params_id, + m_is_variadic); +} + + /* The implementation of class gcc::jit::recording::block. */ /* Create a recording::eval instance and add it to @@ -2750,6 +3638,19 @@ recording::block::make_debug_string () (void *)this); } +/* Implementation of recording::memento::write_reproducer for blocks. */ + +void +recording::block::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "block"); + r.write (" gcc_jit_block *%s =\n" + " gcc_jit_function_new_block (%s, %s);\n", + id, + r.get_identifier (m_func), + m_name ? m_name->get_debug_string () : "NULL"); +} + /* Dump a block in graphviz form into PP, capturing the block name (if any) and the statements. */ @@ -2856,6 +3757,35 @@ recording::global::write_to_dump (dump &d) get_debug_string ()); } +/* A table of enum gcc_jit_global_kind values expressed in string + form. */ + +static const char * const global_kind_reproducer_strings[] = { + "GCC_JIT_GLOBAL_EXPORTED", + "GCC_JIT_GLOBAL_INTERNAL", + "GCC_JIT_GLOBAL_IMPORTED" +}; + +/* Implementation of recording::memento::write_reproducer for globals. */ + +void +recording::global::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "block"); + r.write (" gcc_jit_lvalue *%s =\n" + " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* enum gcc_jit_global_kind kind */\n" + " %s, /* gcc_jit_type *type */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + global_kind_reproducer_strings[m_kind], + r.get_identifier_as_type (get_type ()), + m_name->get_debug_string ()); +} + /* The implementation of the various const-handling classes: gcc::jit::recording::memento_of_new_rvalue_from_const . */ @@ -2878,9 +3808,10 @@ memento_of_new_rvalue_from_const ::replay_into (replayer *r) m_value)); } -/* The make_debug_string method varies between the various - memento_of_new_rvalue_from_const classes, so we explicitly - write specializations of it. +/* The make_debug_string and write_reproducer methods vary between the + various + memento_of_new_rvalue_from_const + classes, so we explicitly write specializations of them. I (dmalcolm) find the code to be clearer if the "recording" vs "playback" namespaces are written out explicitly, which is why most of this file @@ -2908,6 +3839,23 @@ memento_of_new_rvalue_from_const ::make_debug_string () m_value); } +/* The write_reproducer specialization for . */ + +template <> +void +memento_of_new_rvalue_from_const ::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_type *numeric_type */\n" + " %i); /* int value */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + m_value); +} + /* The make_debug_string specialization for , rendering it as (TARGET_TYPE)LITERAL e.g. @@ -2923,6 +3871,44 @@ memento_of_new_rvalue_from_const ::make_debug_string () m_value); } +/* The write_reproducer specialization for . */ + +template <> +void +recording::memento_of_new_rvalue_from_const ::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + + /* We have to special-case LONG_MIN, since e.g. + -9223372036854775808L + is parsed as + -(9223372036854775808L) + and hence we'd get: + error: integer constant is so large that it is unsigned [-Werror] + Workaround this by writing (LONG_MIN + 1) - 1. */ + if (m_value == LONG_MIN) + { + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_type *numeric_type */\n" + " %ldL - 1); /* long value */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + m_value + 1);; + return; + } + + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_type *numeric_type */\n" + " %ldL); /* long value */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + m_value); + } + /* The make_debug_string specialization for , rendering it as (TARGET_TYPE)LITERAL e.g. @@ -2938,6 +3924,23 @@ memento_of_new_rvalue_from_const ::make_debug_string () m_value); } +/* The write_reproducer specialization for . */ + +template <> +void +recording::memento_of_new_rvalue_from_const ::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_type *numeric_type */\n" + " %f); /* double value */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + m_value); +} + /* The make_debug_string specialization for , rendering it as (TARGET_TYPE)HEX e.g. @@ -2960,8 +3963,34 @@ memento_of_new_rvalue_from_const ::make_debug_string () m_type->get_debug_string ()); } -/* We're done specializing make_debug_string, so we can exit the - gcc::jit::recording namespace. */ +/* Implementation of recording::memento::write_reproducer for + values. */ + +template <> +void +memento_of_new_rvalue_from_const ::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + if (m_value) + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_type *pointer_type */\n" + " (void *)%p); /* void *value */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + m_value); + else + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n" + " %s); /* gcc_jit_type *pointer_type */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type)); +} + +/* We're done specializing make_debug_string and write_reproducer, so we + can exit the gcc::jit::recording namespace. */ } // namespace recording @@ -2986,6 +4015,21 @@ recording::memento_of_new_string_literal::make_debug_string () m_value->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for string literal + values. */ + +void +recording::memento_of_new_string_literal::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n" + " %s); /* const char *value */\n", + id, + r.get_identifier (get_context ()), + m_value->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::unary_op. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3027,6 +4071,33 @@ recording::unary_op::make_debug_string () m_a->get_debug_string ()); } +static const char * const unary_op_reproducer_strings[] = { + "GCC_JIT_UNARY_OP_MINUS", + "GCC_JIT_UNARY_OP_BITWISE_NEGATE", + "GCC_JIT_UNARY_OP_LOGICAL_NEGATE", + "GCC_JIT_UNARY_OP_ABS" +}; + +/* Implementation of recording::memento::write_reproducer for unary ops. */ + +void +recording::unary_op::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_unary_op (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* enum gcc_jit_unary_op op */\n" + " %s, /* gcc_jit_type *result_type */\n" + " %s); /* gcc_jit_rvalue *a */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + unary_op_reproducer_strings[m_op], + r.get_identifier_as_type (get_type ()), + r.get_identifier_as_rvalue (m_a)); +} + /* The implementation of class gcc::jit::recording::binary_op. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3079,6 +4150,43 @@ recording::binary_op::make_debug_string () m_b->get_debug_string ()); } +static const char * const binary_op_reproducer_strings[] = { + "GCC_JIT_BINARY_OP_PLUS", + "GCC_JIT_BINARY_OP_MINUS", + "GCC_JIT_BINARY_OP_MULT", + "GCC_JIT_BINARY_OP_DIVIDE", + "GCC_JIT_BINARY_OP_MODULO", + "GCC_JIT_BINARY_OP_BITWISE_AND", + "GCC_JIT_BINARY_OP_BITWISE_XOR", + "GCC_JIT_BINARY_OP_BITWISE_OR", + "GCC_JIT_BINARY_OP_LOGICAL_AND", + "GCC_JIT_BINARY_OP_LOGICAL_OR", + "GCC_JIT_BINARY_OP_LSHIFT", + "GCC_JIT_BINARY_OP_RSHIFT" +}; + +/* Implementation of recording::memento::write_reproducer for binary ops. */ + +void +recording::binary_op::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_binary_op (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* enum gcc_jit_binary_op op */\n" + " %s, /* gcc_jit_type *result_type */\n" + " %s, /* gcc_jit_rvalue *a */\n" + " %s); /* gcc_jit_rvalue *b */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + binary_op_reproducer_strings[m_op], + r.get_identifier_as_type (get_type ()), + r.get_identifier_as_rvalue (m_a), + r.get_identifier_as_rvalue (m_b)); +} + /* The implementation of class gcc::jit::recording::comparison. */ /* Implementation of recording::memento::make_debug_string for @@ -3104,6 +4212,39 @@ recording::comparison::make_debug_string () m_b->get_debug_string ()); } +/* A table of enum gcc_jit_comparison values expressed in string + form. */ + +static const char * const comparison_reproducer_strings[] = +{ + "GCC_JIT_COMPARISON_EQ", + "GCC_JIT_COMPARISON_NE", + "GCC_JIT_COMPARISON_LT", + "GCC_JIT_COMPARISON_LE", + "GCC_JIT_COMPARISON_GT", + "GCC_JIT_COMPARISON_GE" +}; + +/* Implementation of recording::memento::write_reproducer for comparisons. */ + +void +recording::comparison::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_comparison (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* enum gcc_jit_comparison op */\n" + " %s, /* gcc_jit_rvalue *a */\n" + " %s); /* gcc_jit_rvalue *b */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + comparison_reproducer_strings[m_op], + r.get_identifier_as_rvalue (m_a), + r.get_identifier_as_rvalue (m_b)); +} + /* Implementation of pure virtual hook recording::memento::replay_into for recording::comparison. */ @@ -3157,6 +4298,24 @@ recording::cast::make_debug_string () m_rvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for casts. */ + +void +recording::cast::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_cast (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *rvalue */\n" + " %s); /* gcc_jit_type *type */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_rvalue), + r.get_identifier_as_type (get_type ())); +} + /* The implementation of class gcc::jit::recording::call. */ /* The constructor for gcc::jit::recording::call. */ @@ -3242,6 +4401,31 @@ recording::call::make_debug_string () return result; } +void +recording::call::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "call"); + const char *args_id = r.make_tmp_identifier ("args_for_", this); + r.write (" gcc_jit_rvalue *%s[%i] = {\n", + args_id, + m_args.length ()); + for (unsigned i = 0; i< m_args.length (); i++) + r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i])); + r.write (" };\n"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_function *func */\n" + " %i, /* int numargs */ \n" + " %s); /* gcc_jit_rvalue **args*/\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier (m_func), + m_args.length (), + args_id); +} + /* The implementation of class gcc::jit::recording::call_through_ptr. */ /* The constructor for recording::call_through_ptr. */ @@ -3330,6 +4514,34 @@ recording::call_through_ptr::make_debug_string () return result; } +/* Implementation of recording::memento::write_reproducer for + call_through_ptr. */ + +void +recording::call_through_ptr::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "call"); + const char *args_id = r.make_tmp_identifier ("args_for_", this); + r.write (" gcc_jit_rvalue *%s[%i] = {\n", + args_id, + m_args.length ()); + for (unsigned i = 0; i< m_args.length (); i++) + r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i])); + r.write (" };\n"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *fn_ptr */\n" + " %i, /* int numargs */ \n" + " %s); /* gcc_jit_rvalue **args*/\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_fn_ptr), + m_args.length (), + args_id); +} + /* The implementation of class gcc::jit::recording::array_access. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3366,6 +4578,25 @@ recording::array_access::make_debug_string () m_index->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + array_access. */ + +void +recording::array_access::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "lvalue"); + r.write (" gcc_jit_lvalue *%s = \n" + " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n" + " %s, /*gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *ptr */\n" + " %s); /* gcc_jit_rvalue *index */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_ptr), + r.get_identifier_as_rvalue (m_index)); +} + /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3402,6 +4633,23 @@ recording::access_field_of_lvalue::make_debug_string () m_field->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + access_field_of_lvalue. */ + +void +recording::access_field_of_lvalue::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "lvalue"); + r.write (" gcc_jit_lvalue *%s = \n" + " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n" + " %s, /*gcc_jit_location *loc */\n" + " %s);\n", + id, + r.get_identifier_as_lvalue (m_lvalue), + r.get_identifier (m_loc), + r.get_identifier (m_field)); +} + /* The implementation of class gcc::jit::recording::access_field_rvalue. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3437,6 +4685,23 @@ recording::access_field_rvalue::make_debug_string () m_field->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + access_field_rvalue. */ + +void +recording::access_field_rvalue::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s = \n" + " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n" + " %s, /*gcc_jit_location *loc */\n" + " %s);\n", + id, + r.get_identifier_as_rvalue (m_rvalue), + r.get_identifier (m_loc), + r.get_identifier (m_field)); +} + /* The implementation of class gcc::jit::recording::dereference_field_rvalue. */ @@ -3473,6 +4738,23 @@ recording::dereference_field_rvalue::make_debug_string () m_field->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + dereference_field_rvalue. */ + +void +recording::dereference_field_rvalue::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "lvalue"); + r.write (" gcc_jit_lvalue *%s=\n" + " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* gcc_jit_field *field */\n", + id, + r.get_identifier_as_rvalue (m_rvalue), + r.get_identifier (m_loc), + r.get_identifier (m_field)); +} + /* The implementation of class gcc::jit::recording::dereference_rvalue. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3506,6 +4788,21 @@ recording::dereference_rvalue::make_debug_string () m_rvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + dereference_rvalue. */ + +void +recording::dereference_rvalue::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "dereference"); + r.write (" gcc_jit_lvalue *%s =\n" + " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n" + " %s); /* gcc_jit_location *loc */\n", + id, + r.get_identifier_as_rvalue (m_rvalue), + r.get_identifier (m_loc)); +} + /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3539,6 +4836,21 @@ recording::get_address_of_lvalue::make_debug_string () m_lvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + get_address_of_lvalue. */ + +void +recording::get_address_of_lvalue::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "address_of"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n" + " %s); /* gcc_jit_location *loc */\n", + id, + r.get_identifier_as_lvalue (m_lvalue), + r.get_identifier (m_loc)); +} + /* The implementation of class gcc::jit::recording::local. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3570,6 +4882,22 @@ recording::local::write_to_dump (dump &d) get_debug_string ()); } +void +recording::local::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "local"); + r.write (" gcc_jit_lvalue *%s =\n" + " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *type */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (m_func), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type), + m_name->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::statement. */ /* We poison the default implementation of @@ -3624,6 +4952,20 @@ recording::eval::make_debug_string () m_rvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + eval statements. */ + +void +recording::eval::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* gcc_jit_rvalue *rvalue */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier_as_rvalue (m_rvalue)); +} + /* The implementation of class gcc::jit::recording::assignment. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3650,6 +4992,22 @@ recording::assignment::make_debug_string () m_rvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + assignment statements. */ + +void +recording::assignment::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_lvalue *lvalue */\n" + " %s); /* gcc_jit_rvalue *rvalue */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier_as_lvalue (m_lvalue), + r.get_identifier_as_rvalue (m_rvalue)); +} + /* The implementation of class gcc::jit::recording::assignment_op. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3687,6 +5045,24 @@ recording::assignment_op::make_debug_string () m_rvalue->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + assignment_op statements. */ + +void +recording::assignment_op::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_lvalue *lvalue */\n" + " %s, /* enum gcc_jit_binary_op op */\n" + " %s); /* gcc_jit_rvalue *rvalue */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier_as_lvalue (m_lvalue), + binary_op_reproducer_strings[m_op], + r.get_identifier_as_rvalue (m_rvalue)); +} + /* The implementation of class gcc::jit::recording::comment. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3711,6 +5087,20 @@ recording::comment::make_debug_string () m_text->c_str ()); } +/* Implementation of recording::memento::write_reproducer for + comments. */ + +void +recording::comment::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* const char *text */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + m_text->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::conditional. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3759,6 +5149,24 @@ recording::conditional::make_debug_string () m_on_true->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + conditional statements. */ + +void +recording::conditional::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *boolval */\n" + " %s, /* gcc_jit_block *on_true */\n" + " %s); /* gcc_jit_block *on_false */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier_as_rvalue (m_boolval), + r.get_identifier (m_on_true), + r.get_identifier (m_on_false)); +} + /* The implementation of class gcc::jit::recording::jump. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3796,6 +5204,20 @@ recording::jump::make_debug_string () m_target->get_debug_string ()); } +/* Implementation of recording::memento::write_reproducer for + jump statements. */ + +void +recording::jump::write_reproducer (reproducer &r) +{ + r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* gcc_jit_block *target */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier (m_target)); +} + /* The implementation of class gcc::jit::recording::return_. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -3836,6 +5258,26 @@ recording::return_::make_debug_string () "return;"); } +/* Implementation of recording::memento::write_reproducer for + return statements. */ + +void +recording::return_::write_reproducer (reproducer &r) +{ + if (m_rvalue) + r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* gcc_jit_rvalue *rvalue */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ()), + r.get_identifier_as_rvalue (m_rvalue)); + else + r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n" + " %s); /* gcc_jit_location *loc */\n", + r.get_identifier (get_block ()), + r.get_identifier (get_loc ())); +} + } // namespace gcc::jit } // namespace gcc diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 812205c0a1b..57e71675c37 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -30,6 +30,7 @@ namespace jit { class result; class dump; +class reproducer; /********************************************************************** Recording. @@ -73,7 +74,8 @@ public: location * new_location (const char *filename, int line, - int column); + int column, + bool created_by_user); type * get_type (enum gcc_jit_types type); @@ -244,6 +246,8 @@ public: void dump_to_file (const char *path, bool update_locations); + void dump_reproducer_to_file (const char *path); + void get_all_requested_dumps (vec *out); @@ -253,6 +257,10 @@ private: private: context *m_parent_ctxt; + /* The ultimate ancestor of the contexts within a family tree of + contexts. This has itself as its own m_toplevel_ctxt. */ + context *m_toplevel_ctxt; + int m_error_count; char *m_first_error_str; @@ -314,6 +322,8 @@ public: get_debug_string (); virtual void write_to_dump (dump &d); + virtual void write_reproducer (reproducer &r) = 0; + virtual location *dyn_cast_location () { return NULL; } protected: memento (context *ctxt) @@ -355,6 +365,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: size_t m_len; @@ -364,11 +375,13 @@ private: class location : public memento { public: - location (context *ctxt, string *filename, int line, int column) + location (context *ctxt, string *filename, int line, int column, + bool created_by_user) : memento (ctxt), m_filename (filename), m_line (line), - m_column (column) + m_column (column), + m_created_by_user (created_by_user) {} void replay_into (replayer *r); @@ -400,13 +413,18 @@ public: return static_cast (m_playback_obj); } + location *dyn_cast_location () { return this; } + bool created_by_user () const { return m_created_by_user; } + private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: string *m_filename; int m_line; int m_column; + bool m_created_by_user; }; class type : public memento @@ -458,6 +476,8 @@ public: return static_cast (m_playback_obj); } + virtual const char *access_as_type (reproducer &r); + protected: type (context *ctxt) : memento (ctxt), @@ -504,6 +524,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: enum gcc_jit_types m_kind; @@ -531,6 +552,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: type *m_other_type; @@ -565,6 +587,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: type *m_other_type; @@ -593,6 +616,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: type *m_other_type; @@ -623,6 +647,7 @@ class array_type : public type private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: location *m_loc; @@ -657,9 +682,14 @@ public: string * make_debug_string_with_ptr (); + void + write_deferred_reproducer (reproducer &r, + memento *ptr_type); + private: string * make_debug_string (); string * make_debug_string_with (const char *); + void write_reproducer (reproducer &r); private: type *m_return_type; @@ -698,6 +728,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: location *m_loc; @@ -757,9 +788,11 @@ public: void replay_into (replayer *r); + const char *access_as_type (reproducer &r); + private: string * make_debug_string (); - + void write_reproducer (reproducer &r); }; // memento of struct_::set_fields @@ -774,8 +807,12 @@ public: void write_to_dump (dump &d); + int length () const { return m_fields.length (); } + field *get_field (int i) const { return m_fields[i]; } + private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: compound_type *m_struct_or_union; @@ -793,11 +830,11 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: location *m_loc; string *m_name; - fields *m_fields; }; /* An abstract base class for operations that visit all rvalues within an @@ -861,6 +898,8 @@ public: /* Dynamic cast. */ virtual param *dyn_cast_param () { return NULL; } + virtual const char *access_as_rvalue (reproducer &r); + protected: location *m_loc; type *m_type; @@ -893,6 +932,9 @@ public: rvalue * as_rvalue () { return this; } + + const char *access_as_rvalue (reproducer &r); + virtual const char *access_as_lvalue (reproducer &r); }; class param : public lvalue @@ -920,8 +962,12 @@ public: param *dyn_cast_param () { return this; } + const char *access_as_rvalue (reproducer &r); + const char *access_as_lvalue (reproducer &r); + private: string * make_debug_string () { return m_name; } + void write_reproducer (reproducer &r); private: string *m_name; @@ -978,6 +1024,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: location *m_loc; @@ -1065,6 +1112,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); void replay_into (replayer *r); @@ -1103,6 +1151,7 @@ public: private: string * make_debug_string () { return m_name; } + void write_reproducer (reproducer &r); private: enum gcc_jit_global_kind m_kind; @@ -1126,6 +1175,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: HOST_TYPE m_value; @@ -1146,6 +1196,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: string *m_value; @@ -1170,6 +1221,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: enum gcc_jit_unary_op m_op; @@ -1195,6 +1247,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: enum gcc_jit_binary_op m_op; @@ -1221,6 +1274,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: enum gcc_jit_comparison m_op; @@ -1245,6 +1299,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; @@ -1265,6 +1320,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: function *m_func; @@ -1286,6 +1342,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_fn_ptr; @@ -1310,6 +1367,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_ptr; @@ -1334,6 +1392,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: lvalue *m_lvalue; @@ -1358,6 +1417,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; @@ -1382,6 +1442,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; @@ -1403,6 +1464,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; @@ -1424,6 +1486,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: lvalue *m_lvalue; @@ -1448,6 +1511,7 @@ public: private: string * make_debug_string () { return m_name; } + void write_reproducer (reproducer &r); private: function *m_func; @@ -1495,6 +1559,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; @@ -1515,6 +1580,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: lvalue *m_lvalue; @@ -1538,6 +1604,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: lvalue *m_lvalue; @@ -1558,6 +1625,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: string *m_text; @@ -1583,6 +1651,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_boolval; @@ -1606,6 +1675,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: block *m_target; @@ -1627,6 +1697,7 @@ public: private: string * make_debug_string (); + void write_reproducer (reproducer &r); private: rvalue *m_rvalue; diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 79320f676f7..9b55c91df45 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -106,6 +106,8 @@ namespace gccjit int flags, int verbosity); + void dump_reproducer_to_file (const char *path); + void set_str_option (enum gcc_jit_str_option opt, const char *value); @@ -558,6 +560,13 @@ context::set_logfile (FILE *logfile, verbosity); } +inline void +context::dump_reproducer_to_file (const char *path) +{ + gcc_jit_context_dump_reproducer_to_file (m_inner_ctxt, + path); +} + inline void context::set_str_option (enum gcc_jit_str_option opt, const char *value) diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index ad8ee752d29..a78b3e7514c 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -386,7 +386,7 @@ gcc_jit_context_new_location (gcc_jit_context *ctxt, { RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); JIT_LOG_FUNC (ctxt->get_logger ()); - return (gcc_jit_location *)ctxt->new_location (filename, line, column); + return (gcc_jit_location *)ctxt->new_location (filename, line, column, true); } /* Public entrypoint. See description in libgccjit.h. @@ -2234,6 +2234,22 @@ gcc_jit_context_set_logfile (gcc_jit_context *ctxt, ctxt->set_logger (logger); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::dump_reproducer_to_file method in + jit-recording.c. */ + +void +gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt, + const char *path) +{ + RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); + ctxt->dump_reproducer_to_file (path); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 41c76eacdec..2f410875c82 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1051,6 +1051,24 @@ gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt); Implementation support. **********************************************************************/ +/* Write C source code into "path" that can be compiled into a + self-contained executable (i.e. with libgccjit as the only dependency). + The generated code will attempt to replay the API calls that have been + made into the given context. + + This may be useful when debugging the library or client code, for + reducing a complicated recipe for reproducing a bug into a simpler + form. + + Typically you need to supply the option "-Wno-unused-variable" when + compiling the generated file (since the result of each API call is + assigned to a unique variable within the generated C source, and not + all are necessarily then used). */ + +extern void +gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt, + const char *path); + /* Enable the dumping of a specific set of internal state from the compilation, capturing the result in-memory as a buffer. diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 3ab88fda4b5..93d5c26c8fe 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -33,6 +33,7 @@ gcc_jit_context_acquire; gcc_jit_context_compile; gcc_jit_context_dump_to_file; + gcc_jit_context_dump_reproducer_to_file; gcc_jit_context_enable_dump; gcc_jit_context_get_builtin_function; gcc_jit_context_get_first_error; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cb15553f14e..334e3e5af65 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2015-01-13 David Malcolm + + * jit.dg/harness.h (set_up_logging): Move string concatenation + into... + (concat_strings): New function. + (dump_reproducer): New function. + (test_jit): Call dump_reproducer. + * jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer): New + function. + (jit-dg-test): Delete any generated reproducer from previous runs. + Verify that a generated reproducer was created, and verify that it + compiles. + * jit.dg/test-nested-contexts.c (main): Call + gcc_jit_context_dump_reproducer_to_file. + 2015-01-13 H.J. Lu * gcc.dg/aru-2.c: Add dg-require-profiling. diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h index 1252af5e4c7..6bbe7a7b283 100644 --- a/gcc/testsuite/jit.dg/harness.h +++ b/gcc/testsuite/jit.dg/harness.h @@ -250,6 +250,23 @@ static void set_options (gcc_jit_context *ctxt, const char *argv0) 0); } +/* Concatenate two strings. The result must be released using "free". */ + +char * +concat_strings (const char *prefix, const char *suffix) +{ + char *result = (char *)malloc (strlen (prefix) + strlen (suffix) + 1); + if (!result) + { + fail ("malloc failure"); + return NULL; + } + strcpy (result, prefix); + strcpy (result + strlen (prefix), suffix); + result[strlen (prefix) + strlen (suffix)] = '\0'; + return result; +} + #ifndef TEST_ESCHEWS_TEST_JIT /* Set up logging to a logfile of the form "test-FOO.exe.log.txt". @@ -271,18 +288,9 @@ set_up_logging (gcc_jit_context *ctxt, const char *argv0) FILE *logfile = NULL; /* Build a logfile name of the form "test-FOO.exe.log.txt". */ - logfile_name = (char *)malloc (strlen (argv0) - + strlen (logfile_name_suffix) - + 1); + logfile_name = concat_strings (argv0, logfile_name_suffix); if (!logfile_name) - { - fail ("malloc failure"); - return NULL; - } - strcpy (logfile_name, argv0); - strcpy (logfile_name + strlen (argv0), logfile_name_suffix); - logfile_name[strlen (argv0) + strlen (logfile_name_suffix)] = '\0'; - + return NULL; logfile = fopen (logfile_name, "w"); CHECK_NON_NULL (logfile); free (logfile_name); @@ -293,6 +301,21 @@ set_up_logging (gcc_jit_context *ctxt, const char *argv0) return logfile; } +/* Exercise the API entrypoint: + gcc_jit_context_dump_reproducer_to_file + by calling it on the context, using the path expected by jit.exp. */ +static void +dump_reproducer (gcc_jit_context *ctxt, const char *argv0) +{ + char *reproducer_name; + reproducer_name = concat_strings (argv0, ".reproducer.c"); + if (!reproducer_name) + return; + note ("%s: writing reproducer to %s", test, reproducer_name); + gcc_jit_context_dump_reproducer_to_file (ctxt, reproducer_name); + free (reproducer_name); +} + /* Run one iteration of the test. */ static void test_jit (const char *argv0, void *user_data) @@ -314,6 +337,8 @@ test_jit (const char *argv0, void *user_data) create_code (ctxt, user_data); + dump_reproducer (ctxt, argv0); + /* This actually calls into GCC and runs the build, all in a mutex for now. */ result = gcc_jit_context_compile (ctxt); diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp index 098ce5e9e95..3caccceb3b2 100644 --- a/gcc/testsuite/jit.dg/jit.exp +++ b/gcc/testsuite/jit.dg/jit.exp @@ -301,6 +301,21 @@ set tests [lsort $tests] verbose "tests: $tests" +# Is testcase NAME meant to generate a reproducer? +proc is_testcase_meant_to_generate_a_reproducer {name} { + # We expect most testcases to generate a reproducer. + # The exceptions are the tutorials (which don't have a "test-" + # prefix), and test-threads.c (which is unique). + verbose "is_testcase_meant_to_generate_a_reproducer: $name" + if { [string match "*test-*" $name] } { + if { [string match "*test-threads.c" $name] } { + return 0 + } + return 1 + } + return 0 +} + # libgloss has found the driver (as "xgcc" or "gcc) and stored # its full path as GCC_UNDER_TEST. proc get_path_of_driver {} { @@ -365,6 +380,14 @@ proc jit-dg-test { prog do_what extra_tool_flags } { return } + # Most of the test cases use gcc_jit_context_dump_reproducer_to_file + # as they run to write out a .c file that reproduces their behavior, + # exercising that API. + set generated_reproducer "${output_file}.reproducer.c" + + # Delete any such generated .c file from a previous run. + catch "exec rm -f $generated_reproducer" + # Run the test executable, capturing the PASS/FAIL textual output # from the C API, converting it into the Tcl API. @@ -456,6 +479,54 @@ proc jit-dg-test { prog do_what extra_tool_flags } { restore_ld_library_path_env_vars + # Most of the test cases use gcc_jit_context_dump_reproducer_to_file + # as they run to write out a .c file that reproduces their behavior, + # exercising that API. + + if { [is_testcase_meant_to_generate_a_reproducer $name] } { + verbose "$name is meant to generate a reproducer" + # Verify that a reproducer was generated + if { [file exists $generated_reproducer] == 1} { + pass "found generated reproducer: $generated_reproducer" + set output_file "${generated_reproducer}.exe" + # (this overwrites output_file) + + # Try to compile the generated reproducer + verbose "compilation_function=$compilation_function" + + # The .c file written by gcc_jit_context_dump_reproducer_to_file + # assigns the result of each API call to a unique variable, and not + # all are necessarily used, so we need -Wno-unused-variable. + set options \ + "{additional_flags=$extra_tool_flags -Wno-unused-variable}" + verbose "options=$options" + + set comp_output2 [$compilation_function $generated_reproducer \ + $output_file "executable" $options] + if ![jit_check_compile "generated reproducer from $name" "initial compilation" \ + $output_file $comp_output2] then { + return + } + + # The caller, dg-test, will verify comp_output, which contains + # the output from compiling the testcase and will issue a fail + # if it's non-empty (e.g. containing warnings, the + # "test for excess errors"). + # + # Append the output from compiling the reproducer, so that this is also + # verified: + append comp_output $comp_output2 + + # TODO: we should try to run the built executable + # It's not quite a quine, since it embeds ptrs which could change + # from run to run. + } else { + fail "did not find a generated reproducer: $generated_reproducer" + } + } else { + verbose "$name is not meant to generate a reproducer" + } + return [list $comp_output $output_file] } diff --git a/gcc/testsuite/jit.dg/test-nested-contexts.c b/gcc/testsuite/jit.dg/test-nested-contexts.c index 81b1bb2cb7f..451d69b22a5 100644 --- a/gcc/testsuite/jit.dg/test-nested-contexts.c +++ b/gcc/testsuite/jit.dg/test-nested-contexts.c @@ -626,6 +626,14 @@ main (int argc, char **argv) "dump-of-test-nested-contexts-bottom.c", 1); + /* Dump a reproducer for the bottom context. + The generated reproducer needs to also regenerate the + parent contexts, so this gives us test coverage for + that case. */ + gcc_jit_context_dump_reproducer_to_file ( + bottom_level.ctxt, + "test-nested-contexts.c.exe.reproducer.c"); + gcc_jit_result *bottom_result = gcc_jit_context_compile (bottom_level.ctxt); verify_bottom_code (bottom_level.ctxt, bottom_result); -- 2.30.2