diff --git a/patches/gcc-13.1.0-rustc-codegen-gcc.patch b/patches/gcc-13.1.0-rustc-codegen-gcc.patch
index 81b0431..e92b2ab 100644
--- a/patches/gcc-13.1.0-rustc-codegen-gcc.patch
+++ b/patches/gcc-13.1.0-rustc-codegen-gcc.patch
@@ -1,4 +1,3 @@
-# Contains the commits from https://github.com/antoyo/gcc/ needed for rustc_codegen_gcc to work
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 00000000000..5fab7cf772c
@@ -37,6 +36,437 @@ index 00000000000..5fab7cf772c
+ with:
+ name: libgccjit.so
+ path: /home/runner/work/gcc/build/gcc/libgccjit.so
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 6aed2cda3ca..4c092094343 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -574,6 +574,8 @@ tm_p_file_list=@tm_p_file_list@
+ tm_p_include_list=@tm_p_include_list@
+ tm_d_file_list=@tm_d_file_list@
+ tm_d_include_list=@tm_d_include_list@
++tm_jit_file_list=@tm_jit_file_list@
++tm_jit_include_list=@tm_jit_include_list@
+ build_xm_file_list=@build_xm_file_list@
+ build_xm_include_list=@build_xm_include_list@
+ build_xm_defines=@build_xm_defines@
+@@ -868,6 +870,7 @@ CONFIG_H = config.h $(host_xm_file_list)
+ TCONFIG_H = tconfig.h $(xm_file_list)
+ TM_P_H = tm_p.h $(tm_p_file_list)
+ TM_D_H = tm_d.h $(tm_d_file_list)
++TM_JIT_H = tm_jit.h $(tm_jit_file_list)
+ GTM_H = tm.h $(tm_file_list) insn-constants.h
+ TM_H = $(GTM_H) insn-flags.h $(OPTIONS_H)
+
+@@ -926,10 +929,12 @@ TARGET_DEF = target.def target-hooks-macros.h target-insns.def
+ C_TARGET_DEF = c-family/c-target.def target-hooks-macros.h
+ COMMON_TARGET_DEF = common/common-target.def target-hooks-macros.h
+ D_TARGET_DEF = d/d-target.def target-hooks-macros.h
++JIT_TARGET_DEF = jit/jit-target.def target-hooks-macros.h
+ TARGET_H = $(TM_H) target.h $(TARGET_DEF) insn-modes.h insn-codes.h
+ C_TARGET_H = c-family/c-target.h $(C_TARGET_DEF)
+ COMMON_TARGET_H = common/common-target.h $(INPUT_H) $(COMMON_TARGET_DEF)
+ D_TARGET_H = d/d-target.h $(D_TARGET_DEF)
++JIT_TARGET_H = jit/jit-target.h $(JIT_TARGET_DEF)
+ MACHMODE_H = machmode.h mode-classes.def
+ HOOKS_H = hooks.h
+ HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
+@@ -1230,6 +1235,9 @@ CXX_TARGET_OBJS=@cxx_target_objs@
+ # Target specific, D specific object file
+ D_TARGET_OBJS=@d_target_objs@
+
++# Target specific, JIT specific object file
++JIT_TARGET_OBJS=@jit_target_objs@
++
+ # Target specific, Fortran specific object file
+ FORTRAN_TARGET_OBJS=@fortran_target_objs@
+
+@@ -1947,6 +1955,7 @@ tconfig.h: cs-tconfig.h ; @true
+ tm.h: cs-tm.h ; @true
+ tm_p.h: cs-tm_p.h ; @true
+ tm_d.h: cs-tm_d.h ; @true
++tm_jit.h: cs-tm_jit.h ; @true
+
+ cs-config.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+@@ -1978,6 +1987,11 @@ cs-tm_d.h: Makefile
+ HEADERS="$(tm_d_include_list)" DEFINES="" \
+ $(SHELL) $(srcdir)/mkconfig.sh tm_d.h
+
++cs-tm_jit.h: Makefile
++ TARGET_CPU_DEFAULT="" \
++ HEADERS="$(tm_jit_include_list)" DEFINES="" \
++ $(SHELL) $(srcdir)/mkconfig.sh tm_jit.h
++
+ # Don't automatically run autoconf, since configure.ac might be accidentally
+ # newer than configure. Also, this writes into the source directory which
+ # might be on a read-only file system. If configured for maintainer mode
+@@ -2619,6 +2633,15 @@ s-d-target-hooks-def-h: build/genhooks$(build_exeext)
+ d/d-target-hooks-def.h
+ $(STAMP) s-d-target-hooks-def-h
+
++jit/jit-target-hooks-def.h: s-jit-target-hooks-def-h; @true
++
++s-jit-target-hooks-def-h: build/genhooks$(build_exeext)
++ $(RUN_GEN) build/genhooks$(build_exeext) "JIT Target Hook" \
++ > tmp-jit-target-hooks-def.h
++ $(SHELL) $(srcdir)/../move-if-change tmp-jit-target-hooks-def.h \
++ jit/jit-target-hooks-def.h
++ $(STAMP) s-jit-target-hooks-def-h
++
+ # check if someone mistakenly only changed tm.texi.
+ # We use a different pathname here to avoid a circular dependency.
+ s-tm-texi: $(srcdir)/doc/../doc/tm.texi
+@@ -2794,7 +2817,7 @@ s-gtype: $(EXTRA_GTYPE_DEPS) build/gengtype$(build_exeext) \
+ -r gtype.state
+ $(STAMP) s-gtype
+
+-generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
++generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_JIT_H) $(TM_H) multilib.h \
+ $(simple_generated_h) specs.h \
+ tree-check.h genrtl.h insn-modes.h insn-modes-inline.h \
+ tm-preds.h tm-constrs.h \
+@@ -2803,7 +2826,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
+ common/common-target-hooks-def.h pass-instances.def \
+ gimple-match.cc generic-match.cc \
+ c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
+- case-cfn-macros.h \
++ jit/jit-target-hooks-def.h case-cfn-macros.h \
+ cfn-operators.pd omp-device-properties.h
+
+ #
+@@ -2937,7 +2960,7 @@ build/genrecog.o : genrecog.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
+ $(HASH_TABLE_H) inchash.h
+ build/genhooks.o : genhooks.cc $(TARGET_DEF) $(C_TARGET_DEF) \
+- $(COMMON_TARGET_DEF) $(D_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
++ $(COMMON_TARGET_DEF) $(D_TARGET_DEF) $(JIT_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
+ build/genmddump.o : genmddump.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ build/genmatch.o : genmatch.cc $(BCONFIG_H) $(SYSTEM_H) \
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index c4633e869ac..6a0fc540bcb 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -146,6 +146,9 @@
+ # d_target_objs List of extra target-dependent objects that be
+ # linked into the D compiler only.
+ #
++# jit_target_objs List of extra target-dependent objects that be
++# linked into the jit compiler only.
++#
+ # fortran_target_objs List of extra target-dependent objects that be
+ # linked into the fortran compiler only.
+ #
+@@ -201,6 +204,9 @@
+ #
+ # target_has_targetdm Set to yes or no depending on whether the target
+ # has its own definition of targetdm.
++#
++# target_has_targetjitm Set to yes or no depending on whether the target
++# has its own definition of targetdm.
+
+ out_file=
+ common_out_file=
+@@ -217,10 +223,12 @@ extra_options=
+ c_target_objs=
+ cxx_target_objs=
+ d_target_objs=
++jit_target_objs=
+ fortran_target_objs=
+ target_has_targetcm=no
+ target_has_targetm_common=yes
+ target_has_targetdm=no
++target_has_targetjitm=no
+ tm_defines=
+ xm_defines=
+ # Set this to force installation and use of collect2.
+@@ -338,6 +346,7 @@ aarch64*-*-*)
+ c_target_objs="aarch64-c.o"
+ cxx_target_objs="aarch64-c.o"
+ d_target_objs="aarch64-d.o"
++ #jit_target_objs="aarch64-jit.o"
+ extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
+ target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.cc \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
+ target_has_targetm_common=yes
+@@ -368,6 +377,7 @@ arm*-*-*)
+ c_target_objs="arm-c.o"
+ cxx_target_objs="arm-c.o"
+ d_target_objs="arm-d.o"
++ #jit_target_objs="arm-jit.o"
+ extra_options="${extra_options} arm/arm-tables.opt"
+ target_gtfiles="\$(srcdir)/config/arm/arm-builtins.cc \$(srcdir)/config/arm/arm-mve-builtins.h \$(srcdir)/config/arm/arm-mve-builtins.cc"
+ ;;
+@@ -401,6 +411,7 @@ i[34567]86-*-* | x86_64-*-*)
+ c_target_objs="i386-c.o"
+ cxx_target_objs="i386-c.o"
+ d_target_objs="i386-d.o"
++ jit_target_objs="i386-jit.o"
+ extra_objs="x86-tune-sched.o x86-tune-sched-bd.o x86-tune-sched-atom.o x86-tune-sched-core.o i386-options.o i386-builtins.o i386-expand.o i386-features.o"
+ target_gtfiles="\$(srcdir)/config/i386/i386-builtins.cc \$(srcdir)/config/i386/i386-expand.cc \$(srcdir)/config/i386/i386-options.cc"
+ extra_options="${extra_options} fused-madd.opt"
+@@ -462,6 +473,7 @@ microblaze*-*-*)
+ mips*-*-*)
+ cpu_type=mips
+ d_target_objs="mips-d.o"
++ #jit_target_objs="mips-jit.o"
+ extra_headers="loongson.h loongson-mmiintrin.h msa.h"
+ extra_objs="frame-header-opt.o"
+ extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt"
+@@ -532,6 +544,7 @@ riscv*)
+ extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o riscv-v.o riscv-vsetvl.o"
+ extra_objs="${extra_objs} riscv-vector-builtins.o riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o"
+ d_target_objs="riscv-d.o"
++ #jit_target_objs="riscv-jit.o"
+ extra_headers="riscv_vector.h"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.h"
+@@ -548,11 +561,13 @@ sparc*-*-*)
+ c_target_objs="sparc-c.o"
+ cxx_target_objs="sparc-c.o"
+ d_target_objs="sparc-d.o"
++ #jit_target_objs="sparc-jit.o"
+ extra_headers="visintrin.h"
+ ;;
+ s390*-*-*)
+ cpu_type=s390
+ d_target_objs="s390-d.o"
++ #jit_target_objs="s390-jit.o"
+ extra_options="${extra_options} fused-madd.opt"
+ extra_headers="s390intrin.h htmintrin.h htmxlintrin.h vecintrin.h"
+ ;;
+@@ -588,6 +603,12 @@ then
+ tm_d_file="${tm_d_file} ${cpu_type}/${cpu_type}-d.h"
+ fi
+
++tm_jit_file=
++if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-jit.h
++then
++ tm_jit_file="${tm_jit_file} ${cpu_type}/${cpu_type}-jit.h"
++fi
++
+ extra_modes=
+ if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-modes.def
+ then
+@@ -754,9 +775,11 @@ case ${target} in
+ c_target_objs="${c_target_objs} darwin-c.o"
+ cxx_target_objs="${cxx_target_objs} darwin-c.o"
+ d_target_objs="${d_target_objs} darwin-d.o"
++ #jit_target_objs="${jit_target_objs} darwin-jit.o"
+ fortran_target_objs="darwin-f.o"
+ target_has_targetcm=yes
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ extra_objs="${extra_objs} darwin.o"
+ extra_gcc_objs="darwin-driver.o"
+ default_use_cxa_atexit=yes
+@@ -785,8 +808,10 @@ case ${target} in
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} dragonfly-d.o"
++ #jit_target_objs="${jit_target_objs} dragonfly-jit.o"
+ tmake_file="${tmake_file} t-dragonfly"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-freebsd*)
+ # This is the generic ELF configuration of FreeBSD. Later
+@@ -836,8 +861,10 @@ case ${target} in
+ esac
+ use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} freebsd-d.o"
++ #jit_target_objs="${jit_target_objs} freebsd-jit.o"
+ tmake_file="${tmake_file} t-freebsd"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-fuchsia*)
+ native_system_header_dir=/include
+@@ -910,19 +937,27 @@ case ${target} in
+ case $target in
+ *-*-*linux*)
+ d_target_objs="${d_target_objs} linux-d.o"
++ jit_target_objs="${jit_target_objs} linux-jit.o"
+ target_has_targetdm=yes
++ target_has_targetjitm=yes
+ ;;
+ *-*-kfreebsd*-gnu)
+ d_target_objs="${d_target_objs} kfreebsd-d.o"
++ #jit_target_objs="${jit_target_objs} kfreebsd-jit.o"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-kopensolaris*-gnu)
+ d_target_objs="${d_target_objs} kopensolaris-d.o"
++ #jit_target_objs="${jit_target_objs} kopensolaris-jit.o"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-gnu*)
+ d_target_objs="${d_target_objs} gnu-d.o"
++ #jit_target_objs="${jit_target_objs} gnu-jit.o"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ esac
+ ;;
+@@ -931,6 +966,7 @@ case ${target} in
+ tmake_file="t-netbsd t-slibgcc"
+ extra_objs="${extra_objs} netbsd.o"
+ d_target_objs="${d_target_objs} netbsd-d.o"
++ #jit_target_objs="${jit_target_objs} netbsd-jit.o"
+ gas=yes
+ gnu_ld=yes
+ use_gcc_stdint=wrap
+@@ -940,6 +976,7 @@ case ${target} in
+ nbsd_tm_file="netbsd.h netbsd-stdint.h netbsd-elf.h"
+ default_use_cxa_atexit=yes
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ case ${target} in
+ arm*-* | i[34567]86-* | powerpc*-* | sparc*-* | x86_64-*)
+ default_gnu_indirect_function=yes
+@@ -959,7 +996,9 @@ case ${target} in
+ ;;
+ esac
+ d_target_objs="${d_target_objs} openbsd-d.o"
++ #jit_target_objs="${jit_target_objs} openbsd-jit.o"
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-phoenix*)
+ gas=yes
+@@ -1016,6 +1055,7 @@ case ${target} in
+ c_target_objs="${c_target_objs} sol2-c.o"
+ cxx_target_objs="${cxx_target_objs} sol2-c.o sol2-cxx.o"
+ d_target_objs="${d_target_objs} sol2-d.o"
++ #jit_target_objs="${jit_target_objs} sol2-jit.o"
+ extra_objs="${extra_objs} sol2.o sol2-stubs.o"
+ extra_options="${extra_options} sol2.opt"
+ case ${enable_threads}:${have_pthread_h}:${have_thread_h} in
+@@ -1024,6 +1064,7 @@ case ${target} in
+ ;;
+ esac
+ target_has_targetdm=yes
++ #target_has_targetjitm=yes
+ ;;
+ *-*-*vms*)
+ extra_options="${extra_options} vms/vms.opt"
+@@ -1760,6 +1801,7 @@ hppa*64*-*-linux*)
+ pa/pa64-linux.h"
+ tmake_file="${tmake_file} pa/t-pa pa/t-linux"
+ d_target_objs="${d_target_objs} pa-d.o"
++ #jit_target_objs="${jit_target_objs} pa-jit.o"
+ gas=yes gnu_ld=yes
+ ;;
+ hppa*-*-linux*)
+@@ -1768,6 +1810,7 @@ hppa*-*-linux*)
+ pa/pa32-regs.h pa/pa32-linux.h"
+ tmake_file="${tmake_file} pa/t-pa pa/t-linux"
+ d_target_objs="${d_target_objs} pa-d.o"
++ #jit_target_objs="${jit_target_objs} pa-jit.o"
+ ;;
+ hppa*-*-openbsd*)
+ target_cpu_default="MASK_PA_11"
+@@ -1776,6 +1819,7 @@ hppa*-*-openbsd*)
+ extra_options="${extra_options} openbsd.opt"
+ tmake_file="pa/t-pa"
+ d_target_objs="${d_target_objs} pa-d.o"
++ #jit_target_objs="${jit_target_objs} pa-jit.o"
+ gas=yes
+ gnu_ld=yes
+ ;;
+@@ -1813,6 +1857,7 @@ hppa*64*-*-hpux11*)
+ pa/pa-hpux1010.opt pa/pa64-hpux.opt hpux11.opt"
+ tmake_file="pa/t-pa t-slibgcc"
+ d_target_objs="${d_target_objs} pa-d.o"
++ #jit_target_objs="${jit_target_objs} pa-jit.o"
+ case x${enable_threads} in
+ x | xyes | xposix )
+ thread_file=posix
+@@ -2086,7 +2131,9 @@ i[34567]86-*-cygwin*)
+ c_target_objs="${c_target_objs} msformat-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
+ d_target_objs="${d_target_objs} cygwin-d.o"
++ #jit_target_objs="${jit_target_objs} cygwin-jit.o"
+ target_has_targetdm="yes"
++ #target_has_targetjitm=yes
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
+@@ -2104,7 +2151,9 @@ x86_64-*-cygwin*)
+ c_target_objs="${c_target_objs} msformat-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
+ d_target_objs="${d_target_objs} cygwin-d.o"
++ #jit_target_objs="${jit_target_objs} cygwin-jit.o"
+ target_has_targetdm="yes"
++ #target_has_targetjitm=yes
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
+@@ -2118,8 +2167,10 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
+ c_target_objs="${c_target_objs} winnt-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-c.o"
+ d_target_objs="${d_target_objs} winnt-d.o"
++ #jit_target_objs="${jit_target_objs} winnt-jit.o"
+ target_has_targetcm="yes"
+ target_has_targetdm="yes"
++ #target_has_targetjitm=yes
+ case ${target} in
+ x86_64-*-* | *-w64-*)
+ need_64bit_isa=yes
+@@ -3582,6 +3633,10 @@ if [ "$target_has_targetdm" = "no" ]; then
+ d_target_objs="$d_target_objs default-d.o"
+ fi
+
++if [ "$target_has_targetjitm" = "no" ]; then
++ jit_target_objs="$jit_target_objs default-jit.o"
++fi
++
+ # Support for --with-cpu and related options (and a few unrelated options,
+ # too).
+ case ${with_cpu} in
+@@ -5752,6 +5807,7 @@ case ${target} in
+ c_target_objs="${c_target_objs} ${cpu_type}-c.o"
+ cxx_target_objs="${cxx_target_objs} ${cpu_type}-c.o"
+ d_target_objs="${d_target_objs} ${cpu_type}-d.o"
++ jit_target_objs="${jit_target_objs} ${cpu_type}-jit.o"
+ tmake_file="${cpu_type}/t-${cpu_type} ${tmake_file}"
+ ;;
+
+diff --git a/gcc/config/default-jit.cc b/gcc/config/default-jit.cc
+new file mode 100644
+index 00000000000..6bee98a79ce
+--- /dev/null
++++ b/gcc/config/default-jit.cc
+@@ -0,0 +1,28 @@
++/* Default JIT language target hooks initializer.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm_jit.h"
++#include "jit/jit-target.h"
++#include "jit/jit-target-def.h"
++
++/* Do not include tm.h or tm_p.h here; definitions needed by the target
++ architecture to initialize targetjitm should instead be added to tm_jit.h. */
++
++struct gcc_targetdm targetjitm = TARGETJITM_INITIALIZER;
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index 01192ef4259..37df854ba51 100644
--- a/gcc/config/i386/i386-builtins.cc
@@ -73,6 +503,513 @@ index 01192ef4259..37df854ba51 100644
ix86_init_builtin_types ();
/* Builtins to get CPU type and features. */
+diff --git a/gcc/config/i386/i386-jit.cc b/gcc/config/i386/i386-jit.cc
+new file mode 100644
+index 00000000000..3014baefc30
+--- /dev/null
++++ b/gcc/config/i386/i386-jit.cc
+@@ -0,0 +1,216 @@
++/* Subroutines for the JIT front end on the x86 architecture.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++#define IN_TARGET_CODE 1
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "target.h"
++#include "tm.h"
++#include "tm_jit.h"
++#include "jit/jit-target.h"
++#include "jit/jit-target-def.h"
++
++/* Implement TARGET_JIT_CPU_VERSIONS for x86 targets. */
++
++void
++ix86_jit_target_versions (void)
++{
++ if (TARGET_64BIT)
++ {
++ jit_add_target_info ("target_arch", "x86_64");
++
++ // TODO
++ /*if (TARGET_X32)
++ jit_add_target_info ("target_arch", "D_X32");*/
++ }
++ else
++ jit_add_target_info ("target_arch", "x86");
++}
++
++/* Implement TARGET_JIT_REGISTER_CPU_TARGET_INFO. */
++
++extern const char *host_detect_local_cpu (int argc, const char **argv);
++
++#if TARGET_64BIT_DEFAULT
++const char* x86_bits = "64";
++#else
++const char* x86_bits = "32";
++#endif
++
++void
++ix86_jit_register_target_info (void)
++{
++ const char *params[] = {"arch", x86_bits};
++ const char *arch = host_detect_local_cpu (2, params);
++
++ const char* arg = "-march=";
++ const char* arg_pos = strstr(arch, arg);
++ const char* arg_value = arg_pos + strlen(arg);
++ const char* arg_value_end = strchr(arg_value, ' ');
++
++ size_t len = arg_value_end - arg_value;
++ char *cpu = new char[len];
++ strncpy(cpu, arg_value, len);
++ cpu[len] = '\0';
++ jit_target_set_arch (cpu);
++
++ jit_target_set_128bit_int_support (targetm.scalar_mode_supported_p (TImode));
++
++ free (const_cast (arch));
++
++ if (TARGET_MMX)
++ jit_add_target_info ("target_feature", "mmx");
++ if (TARGET_SSE)
++ jit_add_target_info("target_feature", "sse");
++ if (TARGET_SSE2)
++ jit_add_target_info("target_feature", "sse2");
++ if (TARGET_SSE3)
++ jit_add_target_info("target_feature", "sse3");
++ if (TARGET_SSSE3)
++ jit_add_target_info("target_feature", "ssse3");
++ if (TARGET_SSE4_1)
++ jit_add_target_info("target_feature", "sse4.1");
++ if (TARGET_SSE4_2)
++ jit_add_target_info("target_feature", "sse4.2");
++ if (TARGET_AES)
++ jit_add_target_info("target_feature", "aes");
++ if (TARGET_SHA)
++ jit_add_target_info("target_feature", "sha");
++ if (TARGET_AVX)
++ jit_add_target_info("target_feature", "avx");
++ if (TARGET_AVX2)
++ jit_add_target_info("target_feature", "avx2");
++ if (TARGET_AVX512F)
++ jit_add_target_info("target_feature", "avx512f");
++ if (TARGET_AVX512ER)
++ jit_add_target_info("target_feature", "avx512er");
++ if (TARGET_AVX512CD)
++ jit_add_target_info("target_feature", "avx512cd");
++ if (TARGET_AVX512PF)
++ jit_add_target_info("target_feature", "avx512pf");
++ if (TARGET_AVX512DQ)
++ jit_add_target_info("target_feature", "avx512dq");
++ if (TARGET_AVX512BW)
++ jit_add_target_info("target_feature", "avx512bw");
++ if (TARGET_AVX512VL)
++ jit_add_target_info("target_feature", "avx512vl");
++ if (TARGET_AVX512VBMI)
++ jit_add_target_info("target_feature", "avx512vbmi");
++ if (TARGET_AVX512IFMA)
++ jit_add_target_info("target_feature", "avx512ifma");
++ if (TARGET_AVX512VPOPCNTDQ)
++ jit_add_target_info("target_feature", "avx512vpopcntdq");
++ if (TARGET_FMA)
++ jit_add_target_info("target_feature", "fma");
++ if (TARGET_RTM)
++ jit_add_target_info("target_feature", "rtm");
++ if (TARGET_SSE4A)
++ jit_add_target_info("target_feature", "sse4a");
++ if (TARGET_BMI) {
++ jit_add_target_info("target_feature", "bmi1");
++ jit_add_target_info("target_feature", "bmi");
++ }
++ if (TARGET_BMI2)
++ jit_add_target_info("target_feature", "bmi2");
++ if (TARGET_LZCNT)
++ jit_add_target_info("target_feature", "lzcnt");
++ if (TARGET_TBM)
++ jit_add_target_info("target_feature", "tbm");
++ if (TARGET_POPCNT)
++ jit_add_target_info("target_feature", "popcnt");
++ if (TARGET_RDRND) {
++ jit_add_target_info("target_feature", "rdrand");
++ jit_add_target_info("target_feature", "rdrnd");
++ }
++ if (TARGET_F16C)
++ jit_add_target_info("target_feature", "f16c");
++ if (TARGET_RDSEED)
++ jit_add_target_info("target_feature", "rdseed");
++ if (TARGET_ADX)
++ jit_add_target_info("target_feature", "adx");
++ if (TARGET_FXSR)
++ jit_add_target_info("target_feature", "fxsr");
++ if (TARGET_XSAVE)
++ jit_add_target_info("target_feature", "xsave");
++ if (TARGET_XSAVEOPT)
++ jit_add_target_info("target_feature", "xsaveopt");
++ if (TARGET_XSAVEC)
++ jit_add_target_info("target_feature", "xsavec");
++ if (TARGET_XSAVES)
++ jit_add_target_info("target_feature", "xsaves");
++ if (TARGET_VPCLMULQDQ) {
++ jit_add_target_info("target_feature", "pclmulqdq");
++ jit_add_target_info("target_feature", "vpclmulqdq");
++ }
++ if (TARGET_CMPXCHG16B)
++ jit_add_target_info("target_feature", "cmpxchg16b");
++ if (TARGET_MOVBE)
++ jit_add_target_info("target_feature", "movbe");
++ if (TARGET_AVX512VBMI2)
++ jit_add_target_info("target_feature", "avx512vbmi2");
++ if (TARGET_PKU)
++ jit_add_target_info("target_feature", "pku");
++ if (TARGET_AVX512VNNI)
++ jit_add_target_info("target_feature", "avx512vnni");
++ if (TARGET_AVX512BF16)
++ jit_add_target_info("target_feature", "avx512bf16");
++ if (TARGET_AVX512BITALG)
++ jit_add_target_info("target_feature", "avx512bitalg");
++ if (TARGET_AVX512VP2INTERSECT)
++ jit_add_target_info("target_feature", "avx512vp2intersect");
++ if (TARGET_PCLMUL)
++ jit_add_target_info("target_feature", "pclmul");
++ if (TARGET_GFNI)
++ jit_add_target_info("target_feature", "gfni");
++ if (TARGET_FMA4)
++ jit_add_target_info("target_feature", "fma4");
++ if (TARGET_XOP)
++ jit_add_target_info("target_feature", "xop");
++
++ // this is only enabled by choice in llvm, never by default - TODO determine if gcc enables it
++ // jit_add_target_info("target_feature", "sse-unaligned-mem");
++
++ if (TARGET_VAES)
++ jit_add_target_info("target_feature", "vaes");
++ if (TARGET_LWP)
++ jit_add_target_info("target_feature", "lwp");
++ if (TARGET_FSGSBASE)
++ jit_add_target_info("target_feature", "fsgsbase");
++ if (TARGET_SHSTK)
++ jit_add_target_info("target_feature", "shstk");
++ if (TARGET_PRFCHW)
++ jit_add_target_info("target_feature", "prfchw");
++ if (TARGET_SAHF) // would this be better as TARGET_USE_SAHF?
++ jit_add_target_info("target_feature", "sahf");
++ if (TARGET_MWAITX)
++ jit_add_target_info("target_feature", "mwaitx");
++ if (TARGET_CLZERO)
++ jit_add_target_info("target_feature", "clzero");
++ if (TARGET_CLDEMOTE)
++ jit_add_target_info("target_feature", "cldemote");
++ if (TARGET_PTWRITE)
++ jit_add_target_info("target_feature", "ptwrite");
++ bool hasERMSB = ix86_arch == PROCESSOR_HASWELL || ix86_arch == PROCESSOR_SKYLAKE
++ || ix86_arch == PROCESSOR_SKYLAKE_AVX512 || ix86_arch == PROCESSOR_CANNONLAKE
++ || ix86_arch == PROCESSOR_ICELAKE_CLIENT || ix86_arch == PROCESSOR_ICELAKE_SERVER
++ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_TIGERLAKE
++ || ix86_arch == PROCESSOR_COOPERLAKE;
++ if (hasERMSB)
++ jit_add_target_info("target_feature", "ermsbd");
++}
+diff --git a/gcc/config/i386/i386-jit.h b/gcc/config/i386/i386-jit.h
+new file mode 100644
+index 00000000000..8cfccba405f
+--- /dev/null
++++ b/gcc/config/i386/i386-jit.h
+@@ -0,0 +1,26 @@
++/* Definitions for the jit front end on the x86 architecture.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++/* In i386-jit.cc */
++extern void ix86_jit_target_versions (void);
++extern void ix86_jit_register_target_info (void);
++extern bool ix86_jit_has_stdcall_convention (unsigned int *, unsigned int *);
++
++/* Target hooks for jit language. */
++#define TARGET_JIT_CPU_VERSIONS ix86_jit_target_versions
++#define TARGET_JIT_REGISTER_CPU_TARGET_INFO ix86_jit_register_target_info
++#define TARGET_JIT_HAS_STDCALL_CONVENTION ix86_jit_has_stdcall_convention
+diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386
+index ffdbbdfe8ce..8421b4dba42 100644
+--- a/gcc/config/i386/t-i386
++++ b/gcc/config/i386/t-i386
+@@ -46,6 +46,10 @@ i386-d.o: $(srcdir)/config/i386/i386-d.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
++i386-jit.o: $(srcdir)/config/i386/i386-jit.cc
++ $(COMPILE) $<
++ $(POSTCOMPILE)
++
+ i386-options.o: $(srcdir)/config/i386/i386-options.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+diff --git a/gcc/config/linux-jit.cc b/gcc/config/linux-jit.cc
+new file mode 100644
+index 00000000000..20f0d8b4c65
+--- /dev/null
++++ b/gcc/config/linux-jit.cc
+@@ -0,0 +1,48 @@
++/* Linux support needed only by jit front-end.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "tm_jit.h"
++#include "jit/jit-target.h"
++#include "jit/jit-target-def.h"
++
++// TODO: remove this hook?
++/* Implement TARGET_JIT_OS_VERSIONS for Linux targets. */
++
++static void
++linux_jit_os_builtins (void)
++{
++}
++
++// TODO: remove this hook?
++/* Implement TARGET_JIT_REGISTER_OS_TARGET_INFO for Linux targets. */
++
++static void
++linux_jit_register_target_info (void)
++{
++}
++
++#undef TARGET_JIT_OS_VERSIONS
++#define TARGET_JIT_OS_VERSIONS linux_jit_os_builtins
++
++#undef TARGET_JIT_REGISTER_OS_TARGET_INFO
++#define TARGET_JIT_REGISTER_OS_TARGET_INFO linux_jit_register_target_info
++
++struct gcc_targetjitm targetjitm = TARGETJITM_INITIALIZER;
+diff --git a/gcc/config/t-linux b/gcc/config/t-linux
+index 03966d5ce96..0be3fb24404 100644
+--- a/gcc/config/t-linux
++++ b/gcc/config/t-linux
+@@ -23,3 +23,7 @@ linux.o: $(srcdir)/config/linux.cc
+ linux-d.o: $(srcdir)/config/linux-d.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
++
++linux-jit.o: $(srcdir)/config/linux-jit.cc
++ $(COMPILE) $<
++ $(POSTCOMPILE)
+diff --git a/gcc/configure b/gcc/configure
+index 254f9b6c943..dbbc21381d4 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -645,6 +645,7 @@ GMPINC
+ GMPLIBS
+ target_cpu_default
+ d_target_objs
++jit_target_objs
+ fortran_target_objs
+ cxx_target_objs
+ c_target_objs
+@@ -654,6 +655,8 @@ xm_include_list
+ xm_file_list
+ tm_d_include_list
+ tm_d_file_list
++tm_jit_include_list
++tm_jit_file_list
+ tm_p_include_list
+ tm_p_file_list
+ tm_defines
+@@ -13506,6 +13509,17 @@ for f in $tm_d_file; do
+ esac
+ done
+
++tm_jit_file_list=
++tm_jit_include_list=
++for f in $tm_jit_file; do
++ case $f in
++ * )
++ tm_jit_file_list="${tm_jit_file_list} \$(srcdir)/config/$f"
++ tm_jit_include_list="${tm_jit_include_list} config/$f"
++ ;;
++ esac
++done
++
+ xm_file_list=
+ xm_include_list=
+ for f in $xm_file; do
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index 62bc908b991..0513895f7d9 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -2371,6 +2371,17 @@ for f in $tm_d_file; do
+ esac
+ done
+
++tm_jit_file_list=
++tm_jit_include_list=
++for f in $tm_jit_file; do
++ case $f in
++ * )
++ tm_jit_file_list="${tm_jit_file_list} \$(srcdir)/config/$f"
++ tm_jit_include_list="${tm_jit_include_list} config/$f"
++ ;;
++ esac
++done
++
+ xm_file_list=
+ xm_include_list=
+ for f in $xm_file; do
+@@ -7328,6 +7339,8 @@ AC_SUBST(tm_p_file_list)
+ AC_SUBST(tm_p_include_list)
+ AC_SUBST(tm_d_file_list)
+ AC_SUBST(tm_d_include_list)
++AC_SUBST(tm_jit_file_list)
++AC_SUBST(tm_jit_include_list)
+ AC_SUBST(xm_file_list)
+ AC_SUBST(xm_include_list)
+ AC_SUBST(xm_defines)
+@@ -7336,6 +7349,7 @@ AC_SUBST(c_target_objs)
+ AC_SUBST(cxx_target_objs)
+ AC_SUBST(fortran_target_objs)
+ AC_SUBST(d_target_objs)
++AC_SUBST(jit_target_objs)
+ AC_SUBST(target_cpu_default)
+
+ AC_SUBST_FILE(language_hooks)
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 8fe49c2ba3d..f6f39b079a8 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -115,6 +115,14 @@ initialize @code{targetdm} themselves, they should set
+ @code{target_has_targetdm=yes} in @file{config.gcc}; otherwise a default
+ definition is used.
+
++Similarly, there is a @code{targetjitm} variable for hooks that are
++specific to the jit front end, documented as ``JIT Target Hook''.
++This is declared in @file{jit/jit-target.h}, the initializer
++@code{TARGETJITM_INITIALIZER} in @file{jit/jit-target-def.h}. If targets
++initialize @code{targetjitm} themselves, they should set
++@code{target_has_targetjitm=yes} in @file{config.gcc}; otherwise a default
++definition is used.
++
+ @node Driver
+ @section Controlling the Compilation Driver, @file{gcc}
+ @cindex driver
+@@ -10902,6 +10910,36 @@ if they have external linkage. If this flag is false, then instantiated
+ decls will be emitted as weak symbols. The default is @code{false}.
+ @end deftypevr
+
++@node JIT Language and ABI
++@section JIT ABI parameters
++@cindex parameters, jit abi
++
++@deftypefn {JIT Target Hook} void TARGET_JIT_CPU_VERSIONS (void)
++Declare all environmental version identifiers relating to the target CPU
++using the function @code{builtin_version}, which takes a string representing
++the name of the version. Version identifiers predefined by this hook apply
++to all modules that are being compiled and imported.
++@end deftypefn
++
++@deftypefn {JIT Target Hook} void TARGET_JIT_OS_VERSIONS (void)
++Similarly to @code{TARGET_JIT_CPU_VERSIONS}, but is used for versions
++relating to the target operating system.
++@end deftypefn
++
++@deftypefn {JIT Target Hook} void TARGET_JIT_REGISTER_CPU_TARGET_INFO (void)
++Register all target information keys relating to the target CPU using the
++function @code{jit_add_target_info_handlers}, which takes a
++@samp{struct jit_target_info_spec} (defined in @file{jit/jit-target.h}). The keys
++added by this hook are made available at compile time by the
++@code{__traits(getTargetInfo)} extension, the result is an expression
++describing the requested target information.
++@end deftypefn
++
++@deftypefn {JIT Target Hook} void TARGET_JIT_REGISTER_OS_TARGET_INFO (void)
++Same as @code{TARGET_JIT_CPU_TARGET_INFO}, but is used for keys relating to
++the target operating system.
++@end deftypefn
++
+ @node Named Address Spaces
+ @section Adding support for named address spaces
+ @cindex named address spaces
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 62c49ac46de..b7da440f817 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -115,6 +115,14 @@ initialize @code{targetdm} themselves, they should set
+ @code{target_has_targetdm=yes} in @file{config.gcc}; otherwise a default
+ definition is used.
+
++Similarly, there is a @code{targetjitm} variable for hooks that are
++specific to the jit front end, documented as ``JIT Target Hook''.
++This is declared in @file{jit/jit-target.h}, the initializer
++@code{TARGETJITM_INITIALIZER} in @file{jit/jit-target-def.h}. If targets
++initialize @code{targetjitm} themselves, they should set
++@code{target_has_targetjitm=yes} in @file{config.gcc}; otherwise a default
++definition is used.
++
+ @node Driver
+ @section Controlling the Compilation Driver, @file{gcc}
+ @cindex driver
+@@ -7127,6 +7135,18 @@ floating-point support; they are not included in this mechanism.
+
+ @hook TARGET_D_TEMPLATES_ALWAYS_COMDAT
+
++@node JIT Language and ABI
++@section JIT ABI parameters
++@cindex parameters, jit abi
++
++@hook TARGET_JIT_CPU_VERSIONS
++
++@hook TARGET_JIT_OS_VERSIONS
++
++@hook TARGET_JIT_REGISTER_CPU_TARGET_INFO
++
++@hook TARGET_JIT_REGISTER_OS_TARGET_INFO
++
+ @node Named Address Spaces
+ @section Adding support for named address spaces
+ @cindex named address spaces
diff --git a/gcc/dwarf2asm.cc b/gcc/dwarf2asm.cc
index 65b95fee243..e66cd30c1fe 100644
--- a/gcc/dwarf2asm.cc
@@ -180,6 +1117,50 @@ index 15be1c8db99..7fa2c114cb2 100644
/* Extracts the personality function of DECL and returns the corresponding
libfunc. */
+diff --git a/gcc/genhooks.cc b/gcc/genhooks.cc
+index 8bcf9929207..0d4b13b7a71 100644
+--- a/gcc/genhooks.cc
++++ b/gcc/genhooks.cc
+@@ -35,6 +35,7 @@ static struct hook_desc hook_array[] = {
+ #include "c-family/c-target.def"
+ #include "common/common-target.def"
+ #include "d/d-target.def"
++#include "jit/jit-target.def"
+ #undef DEFHOOK
+ };
+
+diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
+index 248ec45b729..cca0980b423 100644
+--- a/gcc/jit/Make-lang.in
++++ b/gcc/jit/Make-lang.in
+@@ -120,7 +120,7 @@ jit.serial = $(LIBGCCJIT_FILENAME)
+ # Tell GNU make to ignore these if they exist.
+ .PHONY: jit
+
+-jit_OBJS = attribs.o \
++JIT_OBJS = attribs.o \
+ jit/dummy-frontend.o \
+ jit/libgccjit.o \
+ jit/jit-logging.o \
+@@ -129,13 +129,17 @@ jit_OBJS = attribs.o \
+ jit/jit-result.o \
+ jit/jit-tempdir.o \
+ jit/jit-builtins.o \
++ jit/jit-target.o \
+ jit/jit-spec.o \
+ gcc.o
+
+ ifneq (,$(findstring mingw,$(target)))
+-jit_OBJS += jit/jit-w32.o
++JIT_OBJS += jit/jit-w32.o
+ endif
+
++# All language-specific object files for jit.
++jit_OBJS = $(JIT_OBJS) $(JIT_TARGET_OBJS)
++
+ # Use strict warnings for this front end.
+ jit-warn = $(STRICT_WARN)
+
diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
index 0687567bc88..7ef09d71288 100644
--- a/gcc/jit/dummy-frontend.cc
@@ -607,7 +1588,7 @@ index 3ff7447fbf3..5c323411ea9 100644
namespace jit {
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
-index 96e9227af40..0b107754ca8 100644
+index 96e9227af40..6fdda09eb1e 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
@@ -618,7 +1599,15 @@ index 96e9227af40..0b107754ca8 100644
#include "system.h"
#include "coretypes.h"
#include "target.h"
-@@ -280,6 +281,8 @@ get_tree_node_for_type (enum gcc_jit_types type_)
+@@ -46,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "jit-result.h"
+ #include "jit-builtins.h"
+ #include "jit-tempdir.h"
++#include "jit-target.h"
+
+ #ifdef _WIN32
+ #include "jit-w32.h"
+@@ -280,6 +282,8 @@ get_tree_node_for_type (enum gcc_jit_types type_)
case GCC_JIT_TYPE_FLOAT:
return float_type_node;
@@ -627,7 +1616,7 @@ index 96e9227af40..0b107754ca8 100644
case GCC_JIT_TYPE_DOUBLE:
return double_type_node;
case GCC_JIT_TYPE_LONG_DOUBLE:
-@@ -326,7 +329,7 @@ playback::type *
+@@ -326,7 +330,7 @@ playback::type *
playback::context::
new_array_type (playback::location *loc,
playback::type *element_type,
@@ -636,7 +1625,7 @@ index 96e9227af40..0b107754ca8 100644
{
gcc_assert (element_type);
-@@ -407,7 +410,8 @@ playback::compound_type *
+@@ -407,7 +411,8 @@ playback::compound_type *
playback::context::
new_compound_type (location *loc,
const char *name,
@@ -646,7 +1635,7 @@ index 96e9227af40..0b107754ca8 100644
{
gcc_assert (name);
-@@ -417,6 +421,9 @@ new_compound_type (location *loc,
+@@ -417,6 +422,9 @@ new_compound_type (location *loc,
TYPE_NAME (t) = get_identifier (name);
TYPE_SIZE (t) = 0;
@@ -656,7 +1645,7 @@ index 96e9227af40..0b107754ca8 100644
if (loc)
set_tree_location (t, loc);
-@@ -424,7 +431,7 @@ new_compound_type (location *loc,
+@@ -424,7 +432,7 @@ new_compound_type (location *loc,
}
void
@@ -665,7 +1654,7 @@ index 96e9227af40..0b107754ca8 100644
{
/* Compare with c/c-decl.cc: finish_struct. */
tree t = as_tree ();
-@@ -441,6 +448,10 @@ playback::compound_type::set_fields (const auto_vec *fields)
+@@ -441,6 +449,10 @@ playback::compound_type::set_fields (const auto_vec *fields)
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
}
@@ -676,7 +1665,7 @@ index 96e9227af40..0b107754ca8 100644
fieldlist = chainon (x, fieldlist);
}
fieldlist = nreverse (fieldlist);
-@@ -499,6 +510,36 @@ new_param (location *loc,
+@@ -499,6 +511,40 @@ new_param (location *loc,
return new param (this, inner);
}
@@ -696,6 +1685,10 @@ index 96e9227af40..0b107754ca8 100644
+ return "used";
+ case GCC_JIT_FN_ATTRIBUTE_VISIBILITY:
+ return "visibility";
++ case GCC_JIT_FN_ATTRIBUTE_COLD:
++ return "cold";
++ case GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE:
++ return "returns_twice";
+ }
+ return NULL;
+}
@@ -713,7 +1706,7 @@ index 96e9227af40..0b107754ca8 100644
/* Construct a playback::function instance. */
playback::function *
-@@ -509,7 +550,10 @@ new_function (location *loc,
+@@ -509,7 +555,10 @@ new_function (location *loc,
const char *name,
const auto_vec *params,
int is_variadic,
@@ -725,7 +1718,7 @@ index 96e9227af40..0b107754ca8 100644
{
int i;
param *param;
-@@ -532,6 +576,7 @@ new_function (location *loc,
+@@ -532,6 +581,7 @@ new_function (location *loc,
/* FIXME: this uses input_location: */
tree fndecl = build_fn_decl (name, fn_type);
@@ -733,7 +1726,7 @@ index 96e9227af40..0b107754ca8 100644
if (loc)
set_tree_location (fndecl, loc);
-@@ -543,6 +588,14 @@ new_function (location *loc,
+@@ -543,6 +593,14 @@ new_function (location *loc,
DECL_RESULT (fndecl) = resdecl;
DECL_CONTEXT (resdecl) = fndecl;
@@ -748,7 +1741,7 @@ index 96e9227af40..0b107754ca8 100644
if (builtin_id)
{
gcc_assert (loc == NULL);
-@@ -594,6 +647,52 @@ new_function (location *loc,
+@@ -594,6 +652,58 @@ new_function (location *loc,
DECL_ATTRIBUTES (fndecl));
}
@@ -769,6 +1762,12 @@ index 96e9227af40..0b107754ca8 100644
+ TREE_USED (fndecl) = 1;
+ DECL_PRESERVE_P (fndecl) = 1;
+ }
++ /* See handle_returns_twice_attribute in gcc/c-family/c-attribs.cc. */
++ else if (attr == GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE)
++ DECL_IS_RETURNS_TWICE (fndecl) = 1;
++ /* See handle_pure_attribute in gcc/c-family/c-attribs.cc. */
++ else if (attr == GCC_JIT_FN_ATTRIBUTE_PURE)
++ DECL_PURE_P (fndecl) = 1;
+
+ const char* attribute = fn_attribute_to_string (attr);
+ if (attribute)
@@ -801,7 +1800,7 @@ index 96e9227af40..0b107754ca8 100644
function *func = new function (this, fndecl, kind);
m_functions.safe_push (func);
return func;
-@@ -607,7 +706,9 @@ global_new_decl (location *loc,
+@@ -607,7 +717,9 @@ global_new_decl (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name,
@@ -812,7 +1811,7 @@ index 96e9227af40..0b107754ca8 100644
{
gcc_assert (type);
gcc_assert (name);
-@@ -646,15 +747,33 @@ global_new_decl (location *loc,
+@@ -646,15 +758,33 @@ global_new_decl (location *loc,
break;
}
@@ -847,7 +1846,7 @@ index 96e9227af40..0b107754ca8 100644
/* In use by new_global and new_global_initialized. */
playback::lvalue *
-@@ -674,10 +793,12 @@ new_global (location *loc,
+@@ -674,10 +804,12 @@ new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name,
@@ -862,7 +1861,7 @@ index 96e9227af40..0b107754ca8 100644
return global_finalize_lvalue (inner);
}
-@@ -822,9 +943,11 @@ new_global_initialized (location *loc,
+@@ -822,9 +954,11 @@ new_global_initialized (location *loc,
size_t initializer_num_elem,
const void *initializer,
const char *name,
@@ -876,7 +1875,7 @@ index 96e9227af40..0b107754ca8 100644
vec *constructor_elements = NULL;
-@@ -1007,10 +1130,30 @@ playback::context::new_rvalue_from_vector (location *,
+@@ -1007,10 +1141,30 @@ playback::context::new_rvalue_from_vector (location *,
vec_alloc (v, elements.length ());
for (unsigned i = 0; i < elements.length (); ++i)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elements[i]->as_tree ());
@@ -908,7 +1907,7 @@ index 96e9227af40..0b107754ca8 100644
/* Coerce a tree expression into a boolean tree expression. */
tree
-@@ -1527,6 +1670,163 @@ new_array_access (location *loc,
+@@ -1527,6 +1681,163 @@ new_array_access (location *loc,
}
}
@@ -1072,7 +2071,7 @@ index 96e9227af40..0b107754ca8 100644
/* Construct a tree for a field access. */
tree
-@@ -1812,7 +2112,8 @@ playback::lvalue *
+@@ -1812,7 +2123,8 @@ playback::lvalue *
playback::function::
new_local (location *loc,
type *type,
@@ -1082,7 +2081,7 @@ index 96e9227af40..0b107754ca8 100644
{
gcc_assert (type);
gcc_assert (name);
-@@ -1825,6 +2126,8 @@ new_local (location *loc,
+@@ -1825,6 +2137,8 @@ new_local (location *loc,
DECL_CHAIN (inner) = BIND_EXPR_VARS (m_inner_bind_expr);
BIND_EXPR_VARS (m_inner_bind_expr) = inner;
@@ -1091,7 +2090,7 @@ index 96e9227af40..0b107754ca8 100644
if (loc)
set_tree_location (inner, loc);
return new lvalue (m_ctxt, inner);
-@@ -1857,6 +2160,15 @@ playback::function::get_address (location *loc)
+@@ -1857,6 +2171,15 @@ playback::function::get_address (location *loc)
return new rvalue (m_ctxt, t_fnptr);
}
@@ -1107,7 +2106,7 @@ index 96e9227af40..0b107754ca8 100644
/* Build a statement list for the function as a whole out of the
lists of statements for the individual blocks, building labels
for each block. */
-@@ -1875,6 +2187,11 @@ build_stmt_list ()
+@@ -1875,6 +2198,11 @@ build_stmt_list ()
int j;
tree stmt;
@@ -1119,7 +2118,7 @@ index 96e9227af40..0b107754ca8 100644
b->m_label_expr = build1 (LABEL_EXPR,
void_type_node,
b->as_label_decl ());
-@@ -1973,6 +2290,70 @@ add_eval (location *loc,
+@@ -1973,6 +2301,70 @@ add_eval (location *loc,
add_stmt (rvalue->as_tree ());
}
@@ -1190,8 +2189,16 @@ index 96e9227af40..0b107754ca8 100644
/* Add an assignment to the function's statement list. */
void
+@@ -3226,6 +3618,7 @@ replay ()
+ JIT_LOG_SCOPE (get_logger ());
+
+ init_types ();
++ jit_target_init ();
+
+ /* Replay the recorded events: */
+ timevar_push (TV_JIT_REPLAY);
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
-index 43e92d67d74..b767fec6da8 100644
+index 43e92d67d74..d153f4945d8 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -21,7 +21,9 @@ along with GCC; see the file COPYING3. If not see
@@ -1204,7 +2211,7 @@ index 43e92d67d74..b767fec6da8 100644
#include "timevar.h"
#include "varasm.h"
-@@ -41,6 +43,9 @@ namespace jit {
+@@ -41,11 +43,15 @@ namespace jit {
namespace playback {
@@ -1213,8 +2220,16 @@ index 43e92d67d74..b767fec6da8 100644
+
/* playback::context is an abstract base class.
- The two concrete subclasses are:
-@@ -69,7 +74,7 @@ public:
+- The two concrete subclasses are:
++ The three concrete subclasses are:
+ - playback::compile_to_memory
+- - playback::compile_to_file. */
++ - playback::compile_to_file.
++ - playback::get_target_info */
+
+ class context : public log_user
+ {
+@@ -69,7 +75,7 @@ public:
type *
new_array_type (location *loc,
type *element_type,
@@ -1223,7 +2238,7 @@ index 43e92d67d74..b767fec6da8 100644
field *
new_field (location *loc,
-@@ -85,7 +90,8 @@ public:
+@@ -85,7 +91,8 @@ public:
compound_type *
new_compound_type (location *loc,
const char *name,
@@ -1233,7 +2248,7 @@ index 43e92d67d74..b767fec6da8 100644
type *
new_function_type (type *return_type,
-@@ -104,14 +110,19 @@ public:
+@@ -104,14 +111,19 @@ public:
const char *name,
const auto_vec *params,
int is_variadic,
@@ -1255,7 +2270,7 @@ index 43e92d67d74..b767fec6da8 100644
lvalue *
new_global_initialized (location *loc,
-@@ -121,7 +132,9 @@ public:
+@@ -121,7 +133,9 @@ public:
size_t initializer_num_elem,
const void *initializer,
const char *name,
@@ -1266,7 +2281,7 @@ index 43e92d67d74..b767fec6da8 100644
rvalue *
new_ctor (location *log,
-@@ -147,6 +160,12 @@ public:
+@@ -147,6 +161,12 @@ public:
type *type,
const auto_vec &elements);
@@ -1279,7 +2294,7 @@ index 43e92d67d74..b767fec6da8 100644
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
-@@ -191,6 +210,16 @@ public:
+@@ -191,6 +211,16 @@ public:
rvalue *ptr,
rvalue *index);
@@ -1296,7 +2311,7 @@ index 43e92d67d74..b767fec6da8 100644
void
set_str_option (enum gcc_jit_str_option opt,
const char *value);
-@@ -306,7 +335,9 @@ private:
+@@ -306,7 +336,9 @@ private:
enum gcc_jit_global_kind kind,
type *type,
const char *name,
@@ -1307,7 +2322,26 @@ index 43e92d67d74..b767fec6da8 100644
lvalue *
global_finalize_lvalue (tree inner);
-@@ -460,7 +491,7 @@ public:
+@@ -405,6 +437,18 @@ class compile_to_file : public context
+ const char *m_output_path;
+ };
+
++class get_target_info : public context
++{
++ public:
++ get_target_info (recording::context *ctxt) : context (ctxt)
++ {
++ }
++
++ void postprocess (const char *) final override
++ {
++ }
++};
++
+
+ /* A temporary wrapper object.
+ These objects are (mostly) only valid during replay.
+@@ -460,7 +504,7 @@ public:
: type (inner)
{}
@@ -1316,7 +2350,7 @@ index 43e92d67d74..b767fec6da8 100644
};
class field : public wrapper
-@@ -495,7 +526,8 @@ public:
+@@ -495,7 +539,8 @@ public:
lvalue *
new_local (location *loc,
type *type,
@@ -1326,7 +2360,7 @@ index 43e92d67d74..b767fec6da8 100644
block*
new_block (const char *name);
-@@ -503,6 +535,9 @@ public:
+@@ -503,6 +548,9 @@ public:
rvalue *
get_address (location *loc);
@@ -1336,7 +2370,7 @@ index 43e92d67d74..b767fec6da8 100644
void
build_stmt_list ();
-@@ -573,6 +608,12 @@ public:
+@@ -573,6 +621,12 @@ public:
add_eval (location *loc,
rvalue *rvalue);
@@ -1349,7 +2383,7 @@ index 43e92d67d74..b767fec6da8 100644
void
add_assignment (location *loc,
lvalue *lvalue,
-@@ -636,6 +677,7 @@ private:
+@@ -636,6 +690,7 @@ private:
public: // for now
tree m_label_expr;
@@ -1357,7 +2391,7 @@ index 43e92d67d74..b767fec6da8 100644
friend class function;
};
-@@ -813,4 +855,6 @@ extern playback::context *active_playback_ctxt;
+@@ -813,4 +868,6 @@ extern playback::context *active_playback_ctxt;
} // namespace gcc
@@ -1365,7 +2399,7 @@ index 43e92d67d74..b767fec6da8 100644
+
#endif /* JIT_PLAYBACK_H */
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
-index 2ce272267b8..603731b7fd4 100644
+index 2ce272267b8..f962c9748c4 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -840,9 +840,9 @@ recording::context::get_int_type (int num_bytes, int is_signed)
@@ -1539,7 +2573,33 @@ index 2ce272267b8..603731b7fd4 100644
/* Create a recording::case_ instance and add it to this context's list
of mementos.
-@@ -2294,6 +2388,12 @@ recording::type::get_aligned (size_t alignment_in_bytes)
+@@ -1525,6 +1619,25 @@ recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
+ replayer.compile ();
+ }
+
++void
++recording::context::get_target_info ()
++{
++ JIT_LOG_SCOPE (get_logger ());
++
++ log_all_options ();
++
++ if (errors_occurred ())
++ return;
++
++ add_driver_option ("-fsyntax-only");
++
++ /* Set up a get_target_info playback context. */
++ ::gcc::jit::playback::get_target_info replayer (this);
++
++ /* Use it. */
++ replayer.compile ();
++}
++
+ /* Format the given error using printf's conventions, print
+ it to stderr, and add it to the context. */
+
+@@ -2294,6 +2407,12 @@ recording::type::get_aligned (size_t alignment_in_bytes)
return result;
}
@@ -1552,7 +2612,7 @@ index 2ce272267b8..603731b7fd4 100644
/* Given a type, get a vector version of the type.
Implements the post-error-checking part of
-@@ -2372,6 +2472,10 @@ recording::memento_of_get_type::get_size ()
+@@ -2372,6 +2491,10 @@ recording::memento_of_get_type::get_size ()
case GCC_JIT_TYPE_FLOAT:
size = FLOAT_TYPE_SIZE;
break;
@@ -1563,7 +2623,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
size = DOUBLE_TYPE_SIZE;
break;
-@@ -2431,6 +2535,7 @@ recording::memento_of_get_type::dereference ()
+@@ -2431,6 +2554,7 @@ recording::memento_of_get_type::dereference ()
case GCC_JIT_TYPE_INT64_T:
case GCC_JIT_TYPE_INT128_T:
case GCC_JIT_TYPE_FLOAT:
@@ -1571,7 +2631,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
case GCC_JIT_TYPE_COMPLEX_FLOAT:
-@@ -2495,6 +2600,7 @@ recording::memento_of_get_type::is_int () const
+@@ -2495,6 +2619,7 @@ recording::memento_of_get_type::is_int () const
return true;
case GCC_JIT_TYPE_FLOAT:
@@ -1579,7 +2639,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
-@@ -2553,6 +2659,7 @@ recording::memento_of_get_type::is_signed () const
+@@ -2553,6 +2678,7 @@ recording::memento_of_get_type::is_signed () const
case GCC_JIT_TYPE_UINT128_T:
case GCC_JIT_TYPE_FLOAT:
@@ -1587,7 +2647,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
-@@ -2612,6 +2719,7 @@ recording::memento_of_get_type::is_float () const
+@@ -2612,6 +2738,7 @@ recording::memento_of_get_type::is_float () const
return false;
case GCC_JIT_TYPE_FLOAT:
@@ -1595,7 +2655,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return true;
-@@ -2675,6 +2783,7 @@ recording::memento_of_get_type::is_bool () const
+@@ -2675,6 +2802,7 @@ recording::memento_of_get_type::is_bool () const
return false;
case GCC_JIT_TYPE_FLOAT:
@@ -1603,7 +2663,7 @@ index 2ce272267b8..603731b7fd4 100644
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
-@@ -2754,6 +2863,7 @@ static const char * const get_type_strings[] = {
+@@ -2754,6 +2882,7 @@ static const char * const get_type_strings[] = {
"__int32_t", /* GCC_JIT_TYPE_INT32_T */
"__int64_t", /* GCC_JIT_TYPE_INT64_T */
"__int128_t", /* GCC_JIT_TYPE_INT128_T */
@@ -1611,7 +2671,7 @@ index 2ce272267b8..603731b7fd4 100644
};
-@@ -2800,6 +2910,7 @@ static const char * const get_type_enum_strings[] = {
+@@ -2800,6 +2929,7 @@ static const char * const get_type_enum_strings[] = {
"GCC_JIT_TYPE_INT32_T",
"GCC_JIT_TYPE_INT64_T",
"GCC_JIT_TYPE_INT128_T",
@@ -1619,7 +2679,7 @@ index 2ce272267b8..603731b7fd4 100644
};
void
-@@ -3066,7 +3177,7 @@ recording::string *
+@@ -3066,7 +3196,7 @@ recording::string *
recording::array_type::make_debug_string ()
{
return string::from_printf (m_ctxt,
@@ -1628,7 +2688,7 @@ index 2ce272267b8..603731b7fd4 100644
m_element_type->get_debug_string (),
m_num_elements);
}
-@@ -3082,7 +3193,7 @@ recording::array_type::write_reproducer (reproducer &r)
+@@ -3082,7 +3212,7 @@ recording::array_type::write_reproducer (reproducer &r)
" gcc_jit_context_new_array_type (%s,\n"
" %s, /* gcc_jit_location *loc */\n"
" %s, /* gcc_jit_type *element_type */\n"
@@ -1637,7 +2697,7 @@ index 2ce272267b8..603731b7fd4 100644
id,
r.get_identifier (get_context ()),
r.get_identifier (m_loc),
-@@ -3098,11 +3209,13 @@ recording::function_type::function_type (context *ctxt,
+@@ -3098,11 +3228,13 @@ recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
type **param_types,
@@ -1653,7 +2713,7 @@ index 2ce272267b8..603731b7fd4 100644
{
for (int i = 0; i< num_params; i++)
m_param_types.safe_push (param_types[i]);
-@@ -3484,7 +3597,8 @@ recording::struct_::replay_into (replayer *r)
+@@ -3484,7 +3616,8 @@ recording::struct_::replay_into (replayer *r)
set_playback_obj (
r->new_compound_type (playback_location (r, get_loc ()),
get_name ()->c_str (),
@@ -1663,7 +2723,7 @@ index 2ce272267b8..603731b7fd4 100644
}
const char *
-@@ -3538,7 +3652,8 @@ recording::union_::replay_into (replayer *r)
+@@ -3538,7 +3671,8 @@ recording::union_::replay_into (replayer *r)
set_playback_obj (
r->new_compound_type (playback_location (r, get_loc ()),
get_name ()->c_str (),
@@ -1673,7 +2733,7 @@ index 2ce272267b8..603731b7fd4 100644
}
/* Implementation of recording::memento::make_debug_string for
-@@ -3609,7 +3724,7 @@ recording::fields::replay_into (replayer *)
+@@ -3609,7 +3743,7 @@ recording::fields::replay_into (replayer *)
playback_fields.create (m_fields.length ());
for (unsigned i = 0; i < m_fields.length (); i++)
playback_fields.safe_push (m_fields[i]->playback_field ());
@@ -1682,7 +2742,7 @@ index 2ce272267b8..603731b7fd4 100644
}
/* Override the default implementation of
-@@ -3979,6 +4094,11 @@ void recording::lvalue::set_alignment (unsigned bytes)
+@@ -3979,6 +4113,11 @@ void recording::lvalue::set_alignment (unsigned bytes)
m_alignment = bytes;
}
@@ -1694,7 +2754,7 @@ index 2ce272267b8..603731b7fd4 100644
/* The implementation of class gcc::jit::recording::param. */
/* Implementation of pure virtual hook recording::memento::replay_into
-@@ -4044,7 +4164,8 @@ recording::function::function (context *ctxt,
+@@ -4044,7 +4183,8 @@ recording::function::function (context *ctxt,
int num_params,
recording::param **params,
int is_variadic,
@@ -1704,7 +2764,7 @@ index 2ce272267b8..603731b7fd4 100644
: memento (ctxt),
m_loc (loc),
m_kind (kind),
-@@ -4055,7 +4176,10 @@ recording::function::function (context *ctxt,
+@@ -4055,7 +4195,10 @@ recording::function::function (context *ctxt,
m_builtin_id (builtin_id),
m_locals (),
m_blocks (),
@@ -1716,7 +2776,7 @@ index 2ce272267b8..603731b7fd4 100644
{
for (int i = 0; i< num_params; i++)
{
-@@ -4114,7 +4238,40 @@ recording::function::replay_into (replayer *r)
+@@ -4114,7 +4257,40 @@ recording::function::replay_into (replayer *r)
m_name->c_str (),
¶ms,
m_is_variadic,
@@ -1758,7 +2818,7 @@ index 2ce272267b8..603731b7fd4 100644
}
/* Create a recording::local instance and add it to
-@@ -4259,6 +4416,13 @@ recording::function::validate ()
+@@ -4259,6 +4435,13 @@ recording::function::validate ()
/* Iteratively walk the graph of blocks, marking their "m_is_reachable"
flag, starting at the initial block. */
auto_vec worklist (m_blocks.length ());
@@ -1772,7 +2832,7 @@ index 2ce272267b8..603731b7fd4 100644
worklist.safe_push (m_blocks[0]);
while (worklist.length () > 0)
{
-@@ -4347,7 +4511,8 @@ recording::function::get_address (recording::location *loc)
+@@ -4347,7 +4530,8 @@ recording::function::get_address (recording::location *loc)
= m_ctxt->new_function_type (m_return_type,
m_params.length (),
param_types.address (),
@@ -1782,7 +2842,7 @@ index 2ce272267b8..603731b7fd4 100644
m_fn_ptr_type = fn_type->get_pointer ();
}
gcc_assert (m_fn_ptr_type);
-@@ -4357,6 +4522,18 @@ recording::function::get_address (recording::location *loc)
+@@ -4357,6 +4541,18 @@ recording::function::get_address (recording::location *loc)
return result;
}
@@ -1801,7 +2861,7 @@ index 2ce272267b8..603731b7fd4 100644
/* Implementation of recording::memento::make_debug_string for
functions. */
-@@ -4441,6 +4618,31 @@ recording::block::add_eval (recording::location *loc,
+@@ -4441,6 +4637,31 @@ recording::block::add_eval (recording::location *loc,
return result;
}
@@ -1833,7 +2893,7 @@ index 2ce272267b8..603731b7fd4 100644
/* Create a recording::assignment instance and add it to
the block's context's list of mementos, and to the block's
list of statements.
-@@ -4832,12 +5034,16 @@ recording::global::replay_into (replayer *r)
+@@ -4832,12 +5053,16 @@ recording::global::replay_into (replayer *r)
/ m_type->dereference ()->get_size (),
m_initializer,
playback_string (m_name),
@@ -1852,7 +2912,7 @@ index 2ce272267b8..603731b7fd4 100644
if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
global->set_tls_model (recording::tls_models[m_tls_model]);
-@@ -5390,6 +5596,91 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
+@@ -5390,6 +5615,91 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
elements_id);
}
@@ -1944,7 +3004,7 @@ index 2ce272267b8..603731b7fd4 100644
void
recording::ctor::visit_children (rvalue_visitor *v)
{
-@@ -6260,6 +6551,114 @@ recording::array_access::write_reproducer (reproducer &r)
+@@ -6260,6 +6570,114 @@ recording::array_access::write_reproducer (reproducer &r)
r.get_identifier_as_rvalue (m_index));
}
@@ -2059,7 +3119,7 @@ index 2ce272267b8..603731b7fd4 100644
/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
/* Implementation of pure virtual hook recording::memento::replay_into
-@@ -6575,7 +6974,8 @@ recording::local::replay_into (replayer *r)
+@@ -6575,7 +6993,8 @@ recording::local::replay_into (replayer *r)
playback::lvalue *obj = m_func->playback_function ()
->new_local (playback_location (r, m_loc),
m_type->playback_type (),
@@ -2069,7 +3129,7 @@ index 2ce272267b8..603731b7fd4 100644
if (m_reg_name != NULL)
obj->set_register_name (m_reg_name->c_str ());
-@@ -6649,6 +7049,17 @@ recording::statement::write_to_dump (dump &d)
+@@ -6649,6 +7068,17 @@ recording::statement::write_to_dump (dump &d)
m_loc = d.make_location ();
}
@@ -2087,7 +3147,7 @@ index 2ce272267b8..603731b7fd4 100644
/* The implementation of class gcc::jit::recording::eval. */
/* Implementation of pure virtual hook recording::memento::replay_into
-@@ -6687,6 +7098,59 @@ recording::eval::write_reproducer (reproducer &r)
+@@ -6687,6 +7117,59 @@ recording::eval::write_reproducer (reproducer &r)
r.get_identifier_as_rvalue (m_rvalue));
}
@@ -2148,7 +3208,7 @@ index 2ce272267b8..603731b7fd4 100644
/* Implementation of pure virtual hook recording::memento::replay_into
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
-index e1236dec575..68a792a7cd5 100644
+index e1236dec575..929bbe37c3f 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -23,13 +23,21 @@ along with GCC; see the file COPYING3. If not see
@@ -2233,7 +3293,17 @@ index e1236dec575..68a792a7cd5 100644
case_ *
new_case (rvalue *min_value,
rvalue *max_value,
-@@ -527,6 +555,8 @@ public:
+@@ -283,6 +311,9 @@ public:
+ compile_to_file (enum gcc_jit_output_kind output_kind,
+ const char *output_path);
+
++ void
++ get_target_info ();
++
+ void
+ add_error (location *loc, const char *fmt, ...)
+ GNU_PRINTF(3, 4);
+@@ -527,6 +558,8 @@ public:
type *get_aligned (size_t alignment_in_bytes);
type *get_vector (size_t num_units);
@@ -2242,7 +3312,7 @@ index e1236dec575..68a792a7cd5 100644
/* Get the type obtained when dereferencing this type.
This will return NULL if it's not valid to dereference this type.
-@@ -539,6 +569,8 @@ public:
+@@ -539,6 +572,8 @@ public:
these types. */
virtual size_t get_size () { gcc_unreachable (); }
@@ -2251,7 +3321,7 @@ index e1236dec575..68a792a7cd5 100644
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
-@@ -593,9 +625,13 @@ public:
+@@ -593,9 +628,13 @@ public:
protected:
type (context *ctxt)
: memento (ctxt),
@@ -2265,7 +3335,7 @@ index e1236dec575..68a792a7cd5 100644
private:
type *m_pointer_to_this_type;
};
-@@ -613,6 +649,11 @@ public:
+@@ -613,6 +652,11 @@ public:
size_t get_size () final override;
@@ -2277,7 +3347,7 @@ index e1236dec575..68a792a7cd5 100644
bool accepts_writes_from (type *rtype) final override
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
-@@ -664,6 +705,13 @@ public:
+@@ -664,6 +708,13 @@ public:
type *dereference () final override { return m_other_type; }
@@ -2291,7 +3361,7 @@ index e1236dec575..68a792a7cd5 100644
size_t get_size () final override;
bool accepts_writes_from (type *rtype) final override;
-@@ -699,6 +747,7 @@ public:
+@@ -699,6 +750,7 @@ public:
size_t get_size () final override { return m_other_type->get_size (); };
@@ -2299,7 +3369,7 @@ index e1236dec575..68a792a7cd5 100644
bool is_int () const final override { return m_other_type->is_int (); }
bool is_float () const final override { return m_other_type->is_float (); }
bool is_bool () const final override { return m_other_type->is_bool (); }
-@@ -718,10 +767,11 @@ public:
+@@ -718,10 +770,11 @@ public:
memento_of_get_const (type *other_type)
: decorated_type (other_type) {}
@@ -2314,7 +3384,7 @@ index e1236dec575..68a792a7cd5 100644
}
/* Strip off the "const", giving the underlying type. */
-@@ -757,6 +807,13 @@ public:
+@@ -757,6 +810,13 @@ public:
return m_other_type->is_same_type_as (other->is_volatile ());
}
@@ -2328,7 +3398,7 @@ index e1236dec575..68a792a7cd5 100644
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
-@@ -777,11 +834,20 @@ public:
+@@ -777,11 +837,20 @@ public:
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
@@ -2349,7 +3419,7 @@ index e1236dec575..68a792a7cd5 100644
private:
string * make_debug_string () final override;
void write_reproducer (reproducer &r) final override;
-@@ -798,6 +864,13 @@ public:
+@@ -798,6 +867,13 @@ public:
: decorated_type (other_type),
m_num_units (num_units) {}
@@ -2363,7 +3433,7 @@ index e1236dec575..68a792a7cd5 100644
size_t get_num_units () const { return m_num_units; }
vector_type *dyn_cast_vector_type () final override { return this; }
-@@ -831,7 +904,7 @@ class array_type : public type
+@@ -831,7 +907,7 @@ class array_type : public type
array_type (context *ctxt,
location *loc,
type *element_type,
@@ -2372,7 +3442,7 @@ index e1236dec575..68a792a7cd5 100644
: type (ctxt),
m_loc (loc),
m_element_type (element_type),
-@@ -840,12 +913,19 @@ class array_type : public type
+@@ -840,12 +916,19 @@ class array_type : public type
type *dereference () final override;
@@ -2393,7 +3463,7 @@ index e1236dec575..68a792a7cd5 100644
bool is_signed () const final override { return false; }
void replay_into (replayer *) final override;
-@@ -857,7 +937,7 @@ class array_type : public type
+@@ -857,7 +940,7 @@ class array_type : public type
private:
location *m_loc;
type *m_element_type;
@@ -2402,7 +3472,7 @@ index e1236dec575..68a792a7cd5 100644
};
class function_type : public type
-@@ -867,7 +947,8 @@ public:
+@@ -867,7 +950,8 @@ public:
type *return_type,
int num_params,
type **param_types,
@@ -2412,7 +3482,7 @@ index e1236dec575..68a792a7cd5 100644
type *dereference () final override;
function_type *dyn_cast_function_type () final override { return this; }
-@@ -875,6 +956,18 @@ public:
+@@ -875,6 +959,18 @@ public:
bool is_same_type_as (type *other) final override;
@@ -2431,7 +3501,7 @@ index e1236dec575..68a792a7cd5 100644
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
-@@ -887,6 +980,7 @@ public:
+@@ -887,6 +983,7 @@ public:
type * get_return_type () const { return m_return_type; }
const vec &get_param_types () const { return m_param_types; }
int is_variadic () const { return m_is_variadic; }
@@ -2439,7 +3509,7 @@ index e1236dec575..68a792a7cd5 100644
string * make_debug_string_with_ptr ();
-@@ -903,6 +997,7 @@ private:
+@@ -903,6 +1000,7 @@ private:
type *m_return_type;
auto_vec m_param_types;
int m_is_variadic;
@@ -2447,7 +3517,7 @@ index e1236dec575..68a792a7cd5 100644
};
class field : public memento
-@@ -1004,9 +1099,11 @@ public:
+@@ -1004,9 +1102,11 @@ public:
return static_cast (m_playback_obj);
}
@@ -2460,7 +3530,7 @@ index e1236dec575..68a792a7cd5 100644
fields *m_fields;
};
-@@ -1019,6 +1116,13 @@ public:
+@@ -1019,6 +1119,13 @@ public:
struct_ *dyn_cast_struct () final override { return this; }
@@ -2474,7 +3544,7 @@ index e1236dec575..68a792a7cd5 100644
type *
as_type () { return this; }
-@@ -1066,6 +1170,13 @@ public:
+@@ -1066,6 +1173,13 @@ public:
void replay_into (replayer *r) final override;
@@ -2488,7 +3558,7 @@ index e1236dec575..68a792a7cd5 100644
bool is_union () const final override { return true; }
private:
-@@ -1188,7 +1299,8 @@ public:
+@@ -1188,7 +1302,8 @@ public:
m_link_section (NULL),
m_reg_name (NULL),
m_tls_model (GCC_JIT_TLS_MODEL_NONE),
@@ -2498,7 +3568,7 @@ index e1236dec575..68a792a7cd5 100644
{}
playback::lvalue *
-@@ -1208,6 +1320,14 @@ public:
+@@ -1208,6 +1323,14 @@ public:
as_rvalue () { return this; }
const char *access_as_rvalue (reproducer &r) override;
@@ -2513,7 +3583,7 @@ index e1236dec575..68a792a7cd5 100644
virtual const char *access_as_lvalue (reproducer &r);
virtual bool is_global () const { return false; }
void set_tls_model (enum gcc_jit_tls_model model);
-@@ -1221,6 +1341,8 @@ protected:
+@@ -1221,6 +1344,8 @@ protected:
string *m_reg_name;
enum gcc_jit_tls_model m_tls_model;
unsigned m_alignment;
@@ -2522,7 +3592,7 @@ index e1236dec575..68a792a7cd5 100644
};
class param : public lvalue
-@@ -1274,7 +1396,8 @@ public:
+@@ -1274,7 +1399,8 @@ public:
int num_params,
param **params,
int is_variadic,
@@ -2532,7 +3602,7 @@ index e1236dec575..68a792a7cd5 100644
void replay_into (replayer *r) final override;
-@@ -1308,11 +1431,17 @@ public:
+@@ -1308,11 +1434,17 @@ public:
void write_to_dump (dump &d) final override;
@@ -2550,7 +3620,7 @@ index e1236dec575..68a792a7cd5 100644
private:
string * make_debug_string () final override;
-@@ -1329,6 +1458,9 @@ private:
+@@ -1329,6 +1461,9 @@ private:
auto_vec m_locals;
auto_vec m_blocks;
type *m_fn_ptr_type;
@@ -2560,7 +3630,7 @@ index e1236dec575..68a792a7cd5 100644
};
class block : public memento
-@@ -1357,6 +1489,12 @@ public:
+@@ -1357,6 +1492,12 @@ public:
add_eval (location *loc,
rvalue *rvalue);
@@ -2573,7 +3643,7 @@ index e1236dec575..68a792a7cd5 100644
statement *
add_assignment (location *loc,
lvalue *lvalue,
-@@ -1572,6 +1710,27 @@ private:
+@@ -1572,6 +1713,27 @@ private:
string *m_value;
};
@@ -2601,7 +3671,7 @@ index e1236dec575..68a792a7cd5 100644
class memento_of_new_rvalue_from_vector : public rvalue
{
public:
-@@ -1597,6 +1756,33 @@ private:
+@@ -1597,6 +1759,33 @@ private:
auto_vec m_elements;
};
@@ -2635,7 +3705,7 @@ index e1236dec575..68a792a7cd5 100644
class ctor : public rvalue
{
public:
-@@ -1879,6 +2065,64 @@ private:
+@@ -1879,6 +2068,64 @@ private:
rvalue *m_index;
};
@@ -2700,7 +3770,7 @@ index e1236dec575..68a792a7cd5 100644
class access_field_of_lvalue : public lvalue
{
public:
-@@ -2119,6 +2363,31 @@ private:
+@@ -2119,6 +2366,31 @@ private:
rvalue *m_rvalue;
};
@@ -2732,11 +3802,308 @@ index e1236dec575..68a792a7cd5 100644
class assignment : public statement
{
public:
+diff --git a/gcc/jit/jit-target-def.h b/gcc/jit/jit-target-def.h
+new file mode 100644
+index 00000000000..dcb342fafe7
+--- /dev/null
++++ b/gcc/jit/jit-target-def.h
+@@ -0,0 +1,20 @@
++/* jit-target-def.h -- Default initializers for jit target hooks.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 3, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; see the file COPYING3. If not see
++ . */
++
++#include "jit/jit-target-hooks-def.h"
++#include "tree.h"
++#include "hooks.h"
+diff --git a/gcc/jit/jit-target.cc b/gcc/jit/jit-target.cc
+new file mode 100644
+index 00000000000..ad41376fa7f
+--- /dev/null
++++ b/gcc/jit/jit-target.cc
+@@ -0,0 +1,94 @@
++/* jit-target.cc -- Target interface for the jit front end.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++
++#include "tree.h"
++#include "memmodel.h"
++#include "fold-const.h"
++#include "diagnostic.h"
++#include "stor-layout.h"
++#include "tm.h"
++#include "tm_p.h"
++#include "target.h"
++#include "calls.h"
++
++#include "jit-target.h"
++
++#include
++
++static target_info jit_target_info;
++
++/* Initialize all variables of the Target structure. */
++
++void
++jit_target_init ()
++{
++ /* Initialize target info tables, the keys required by the language are added
++ last, so that the OS and CPU handlers can override. */
++ targetjitm.jit_register_cpu_target_info ();
++ targetjitm.jit_register_os_target_info ();
++}
++
++/* Add all target info in HANDLERS to JIT_TARGET_INFO for use by
++ jit_has_target_value(). */
++
++void
++jit_add_target_info (const char *key, const char *value)
++{
++ if (jit_target_info.m_info.find (key) == jit_target_info.m_info.end())
++ jit_target_info.m_info.insert ({key, {value}});
++ else
++ jit_target_info.m_info[key].insert(value);
++}
++
++void
++jit_target_set_arch (const char* arch)
++{
++ jit_target_info.m_arch = arch;
++}
++
++void
++jit_target_set_128bit_int_support (bool support)
++{
++ jit_target_info.m_supports_128bit_int = support;
++}
++
++target_info::~target_info()
++{
++ free (const_cast ((const void *) m_arch));
++}
++
++target_info *
++jit_get_target_info ()
++{
++ target_info *info = new target_info {std::move(jit_target_info)};
++ jit_target_info = target_info{};
++ return info;
++}
++
++bool
++target_info::has_target_value (const char *key, const char *value)
++{
++ if (m_info.find (key) == m_info.end ())
++ return false;
++
++ auto& set = m_info[key];
++ return set.find (value) != set.end ();
++}
+diff --git a/gcc/jit/jit-target.def b/gcc/jit/jit-target.def
+new file mode 100644
+index 00000000000..92648ac25d8
+--- /dev/null
++++ b/gcc/jit/jit-target.def
+@@ -0,0 +1,70 @@
++/* jit-target.def -- Target hook definitions for the jit front end.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 3, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; see the file COPYING3. If not see
++ . */
++
++/* See target-hooks-macros.h for details of macros that should be
++ provided by the including file, and how to use them here. */
++
++#include "target-hooks-macros.h"
++
++#undef HOOK_TYPE
++#define HOOK_TYPE "JIT Target Hook"
++
++HOOK_VECTOR (TARGETJITM_INITIALIZER, gcc_targetjitm)
++
++#undef HOOK_PREFIX
++#define HOOK_PREFIX "TARGET_"
++
++/* Environmental version identifiers relating to the target CPU. */
++DEFHOOK
++(jit_cpu_versions,
++ "Declare all environmental version identifiers relating to the target CPU\n\
++using the function @code{builtin_version}, which takes a string representing\n\
++the name of the version. Version identifiers predefined by this hook apply\n\
++to all modules that are being compiled and imported.",
++ void, (void),
++ hook_void_void)
++
++/* Environmental version identifiers relating to the target OS. */
++DEFHOOK
++(jit_os_versions,
++ "Similarly to @code{TARGET_JIT_CPU_VERSIONS}, but is used for versions\n\
++relating to the target operating system.",
++ void, (void),
++ hook_void_void)
++
++/* getTargetInfo keys relating to the target CPU. */
++DEFHOOK
++(jit_register_cpu_target_info,
++ "Register all target information keys relating to the target CPU using the\n\
++function @code{jit_add_target_info_handlers}, which takes a\n\
++@samp{struct jit_target_info_spec} (defined in @file{jit/jit-target.h}). The keys\n\
++added by this hook are made available at compile time by the\n\
++@code{__traits(getTargetInfo)} extension, the result is an expression\n\
++describing the requested target information.",
++ void, (void),
++ hook_void_void)
++
++/* getTargetInfo keys relating to the target OS. */
++DEFHOOK
++(jit_register_os_target_info,
++ "Same as @code{TARGET_JIT_CPU_TARGET_INFO}, but is used for keys relating to\n\
++the target operating system.",
++ void, (void),
++ hook_void_void)
++
++/* Close the 'struct gcc_targetdm' definition. */
++HOOK_VECTOR_END (C90_EMPTY_HACK)
+diff --git a/gcc/jit/jit-target.h b/gcc/jit/jit-target.h
+new file mode 100644
+index 00000000000..09fd7941c2e
+--- /dev/null
++++ b/gcc/jit/jit-target.h
+@@ -0,0 +1,70 @@
++/* jit-target.h -- Data structure definitions for target-specific jit behavior.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 3, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; see the file COPYING3. If not see
++ . */
++
++#ifndef GCC_JIT_TARGET_H
++#define GCC_JIT_TARGET_H
++
++#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
++#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
++#define DEFHOOK_UNDOC DEFHOOK
++#define HOOKSTRUCT(FRAGMENT) FRAGMENT
++
++#include "jit-target.def"
++
++#include
++#include
++
++static size_t hash_cstr(const char *s)
++{
++ const size_t seed = 0;
++ return std::_Hash_bytes(s, std::strlen(s), seed);
++}
++
++struct CStringHash {
++ size_t operator()(const char* const &string) const {
++ auto res = hash_cstr (string);
++ return res;
++ }
++};
++
++struct CStringEqual {
++ bool operator()(const char* const &string1, const char* const &string2) const {
++ return strcmp (string1, string2) == 0;
++ }
++};
++
++struct target_info {
++ public:
++ ~target_info();
++
++ bool has_target_value (const char *key, const char *value);
++
++ std::unordered_map, CStringHash, CStringEqual> m_info;
++ const char *m_arch = nullptr;
++ bool m_supports_128bit_int = false;
++};
++
++/* Each target can provide their own. */
++extern struct gcc_targetjitm targetjitm;
++
++extern void jit_target_init ();
++extern void jit_target_set_arch (const char* arch);
++extern void jit_target_set_128bit_int_support (bool support);
++extern void jit_add_target_info (const char *key, const char *value);
++extern target_info * jit_get_target_info ();
++
++#endif /* GCC_JIT_TARGET_H */
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
-index 8884128e8d8..bbf94231930 100644
+index 8884128e8d8..050e68b738c 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
-@@ -592,6 +592,20 @@ gcc_jit_type_is_pointer (gcc_jit_type *type)
+@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "libgccjit.h"
+ #include "jit-recording.h"
+ #include "jit-result.h"
++#include "jit-target.h"
+
+ /* The opaque types used by the public API are actually subclasses
+ of the gcc::jit::recording classes. */
+@@ -44,6 +45,10 @@ struct gcc_jit_result : public gcc::jit::result
+ {
+ };
+
++struct gcc_jit_target_info : public target_info
++{
++};
++
+ struct gcc_jit_object : public gcc::jit::recording::memento
+ {
+ };
+@@ -592,6 +597,20 @@ gcc_jit_type_is_pointer (gcc_jit_type *type)
return (gcc_jit_type *)type->is_pointer ();
}
@@ -2757,7 +4124,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
-@@ -751,7 +765,7 @@ gcc_jit_type *
+@@ -751,7 +770,7 @@ gcc_jit_type *
gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_type *element_type,
@@ -2766,7 +4133,7 @@ index 8884128e8d8..bbf94231930 100644
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
-@@ -783,12 +797,13 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
+@@ -783,12 +802,13 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
@@ -2782,7 +4149,7 @@ index 8884128e8d8..bbf94231930 100644
RETURN_NULL_IF_FAIL_PRINTF1 (
!type->is_void (),
ctxt, loc,
-@@ -995,6 +1010,7 @@ size_t
+@@ -995,6 +1015,7 @@ size_t
gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
{
RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type");
@@ -2790,7 +4157,7 @@ index 8884128e8d8..bbf94231930 100644
return struct_type->get_fields ()->length ();
}
-@@ -1745,6 +1761,23 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
+@@ -1745,6 +1766,23 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
reinterpret_cast(values));
}
@@ -2814,7 +4181,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h. */
extern gcc_jit_lvalue *
-@@ -1853,6 +1886,23 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
+@@ -1853,6 +1891,23 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
return global;
}
@@ -2838,7 +4205,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this calls the trivial
-@@ -2422,6 +2472,8 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
+@@ -2422,6 +2477,8 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
@@ -2847,7 +4214,7 @@ index 8884128e8d8..bbf94231930 100644
RETURN_NULL_IF_FAIL_PRINTF3 (
is_valid_cast (rvalue->get_type (), type),
ctxt, loc,
-@@ -2488,6 +2540,60 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
+@@ -2488,6 +2545,60 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index);
}
@@ -2908,7 +4275,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
-@@ -2801,6 +2907,64 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
+@@ -2801,6 +2912,64 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
rvalue->verify_valid_within_stmt (__func__, stmt);
}
@@ -2973,7 +4340,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
-@@ -2821,7 +2985,7 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
+@@ -2821,7 +2990,7 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
compatible_types (lvalue->get_type (),
@@ -2982,7 +4349,7 @@ index 8884128e8d8..bbf94231930 100644
ctxt, loc,
"mismatching types:"
" assignment to %s (type: %s) from %s (type: %s)",
-@@ -2867,7 +3031,7 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block,
+@@ -2867,7 +3036,7 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block,
RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
compatible_types (lvalue->get_type (),
@@ -2991,7 +4358,7 @@ index 8884128e8d8..bbf94231930 100644
ctxt, loc,
"mismatching types:"
" assignment to %s (type: %s) involving %s (type: %s)",
-@@ -3575,6 +3739,27 @@ gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
+@@ -3575,6 +3744,27 @@ gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
ctxt->add_command_line_option (optname);
}
@@ -3019,7 +4386,52 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
The real work is done by the
-@@ -3950,6 +4135,38 @@ gcc_jit_type_get_aligned (gcc_jit_type *type,
+@@ -3664,6 +3854,44 @@ gcc_jit_context_compile_to_file (gcc_jit_context *ctxt,
+ ctxt->compile_to_file (output_kind, output_path);
+ }
+
++gcc_jit_target_info *
++gcc_jit_context_get_target_info (gcc_jit_context *ctxt)
++{
++ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
++ JIT_LOG_FUNC (ctxt->get_logger ());
++
++ ctxt->log ("get_target_info of ctxt: %p", (void *)ctxt);
++
++ ctxt->get_target_info ();
++
++ return (gcc_jit_target_info*) jit_get_target_info ();
++}
++
++void
++gcc_jit_target_info_release (gcc_jit_target_info *info)
++{
++ RETURN_IF_FAIL (info, NULL, NULL, "NULL info");
++ delete info;
++}
++
++int
++gcc_jit_target_info_cpu_supports (gcc_jit_target_info *info,
++ const char *feature)
++{
++ return info->has_target_value ("target_feature", feature);
++}
++
++const char *
++gcc_jit_target_info_arch (gcc_jit_target_info *info)
++{
++ return info->m_arch;
++}
++
++int
++gcc_jit_target_info_supports_128bit_int (gcc_jit_target_info *info)
++{
++ return info->m_supports_128bit_int;
++}
+
+ /* Public entrypoint. See description in libgccjit.h.
+
+@@ -3950,6 +4178,38 @@ gcc_jit_type_get_aligned (gcc_jit_type *type,
return (gcc_jit_type *)type->get_aligned (alignment_in_bytes);
}
@@ -3058,7 +4470,7 @@ index 8884128e8d8..bbf94231930 100644
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
-@@ -4056,6 +4273,74 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+@@ -4056,6 +4316,74 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
(gcc::jit::recording::rvalue **)elements);
}
@@ -3134,10 +4546,20 @@ index 8884128e8d8..bbf94231930 100644
Ideally this would be within parse_basever, but the mutex is only needed
by libgccjit. */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
-index b3c389e93f6..f5537adbc91 100644
+index b3c389e93f6..9663be4a069 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
-@@ -604,7 +604,9 @@ enum gcc_jit_types
+@@ -52,6 +52,9 @@ typedef struct gcc_jit_context gcc_jit_context;
+ /* A gcc_jit_result encapsulates the result of an in-memory compilation. */
+ typedef struct gcc_jit_result gcc_jit_result;
+
++/* A gcc_jit_target_info encapsulates the target info. */
++typedef struct gcc_jit_target_info gcc_jit_target_info;
++
+ /* An object created within a context. Such objects are automatically
+ cleaned up when the context is released.
+
+@@ -604,7 +607,9 @@ enum gcc_jit_types
GCC_JIT_TYPE_INT16_T,
GCC_JIT_TYPE_INT32_T,
GCC_JIT_TYPE_INT64_T,
@@ -3148,7 +4570,7 @@ index b3c389e93f6..f5537adbc91 100644
};
extern gcc_jit_type *
-@@ -652,7 +654,7 @@ extern gcc_jit_type *
+@@ -652,7 +657,7 @@ extern gcc_jit_type *
gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_type *element_type,
@@ -3157,7 +4579,7 @@ index b3c389e93f6..f5537adbc91 100644
/* Struct-handling. */
-@@ -1021,6 +1023,12 @@ extern gcc_jit_lvalue *
+@@ -1021,6 +1026,12 @@ extern gcc_jit_lvalue *
gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
gcc_jit_rvalue *init_value);
@@ -3170,7 +4592,7 @@ index b3c389e93f6..f5537adbc91 100644
#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
/* Set an initial value for a global, which must be an array of
-@@ -1036,6 +1044,9 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
+@@ -1036,6 +1047,9 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
const void *blob,
size_t num_bytes);
@@ -3180,7 +4602,7 @@ index b3c389e93f6..f5537adbc91 100644
/* Upcasting. */
extern gcc_jit_object *
gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
-@@ -1292,6 +1303,18 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
+@@ -1292,6 +1306,18 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index);
@@ -3199,7 +4621,7 @@ index b3c389e93f6..f5537adbc91 100644
/* Field access is provided separately for both lvalues and rvalues. */
/* Accessing a field of an lvalue of struct type, analogous to:
-@@ -1391,6 +1414,38 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
+@@ -1391,6 +1417,38 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
gcc_jit_location *loc,
gcc_jit_rvalue *rvalue);
@@ -3238,7 +4660,7 @@ index b3c389e93f6..f5537adbc91 100644
/* Add evaluation of an rvalue, assigning the result to the given
lvalue.
-@@ -1788,6 +1843,12 @@ extern gcc_jit_rvalue *
+@@ -1788,6 +1846,12 @@ extern gcc_jit_rvalue *
gcc_jit_function_get_address (gcc_jit_function *fn,
gcc_jit_location *loc);
@@ -3251,7 +4673,7 @@ index b3c389e93f6..f5537adbc91 100644
#define LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
-@@ -1806,6 +1867,21 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+@@ -1806,6 +1870,21 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
size_t num_elements,
gcc_jit_rvalue **elements);
@@ -3273,7 +4695,7 @@ index b3c389e93f6..f5537adbc91 100644
#define LIBGCCJIT_HAVE_gcc_jit_version
/* Functions to retrieve libgccjit version.
-@@ -1969,6 +2045,11 @@ gcc_jit_type_is_integral (gcc_jit_type *type);
+@@ -1969,6 +2048,11 @@ gcc_jit_type_is_integral (gcc_jit_type *type);
extern gcc_jit_type *
gcc_jit_type_is_pointer (gcc_jit_type *type);
@@ -3285,10 +4707,26 @@ index b3c389e93f6..f5537adbc91 100644
/* Given a type, return a dynamic cast to a vector type or NULL. */
extern gcc_jit_vector_type *
gcc_jit_type_dyncast_vector (gcc_jit_type *type);
-@@ -1990,6 +2071,40 @@ gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+@@ -1990,6 +2074,59 @@ gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
extern gcc_jit_type *
gcc_jit_type_unqualified (gcc_jit_type *type);
++extern gcc_jit_target_info *
++gcc_jit_context_get_target_info (gcc_jit_context *ctxt);
++
++extern void
++gcc_jit_target_info_release (gcc_jit_target_info *info);
++
++extern int
++gcc_jit_target_info_cpu_supports (gcc_jit_target_info *info,
++ const char *feature);
++
++extern const char *
++gcc_jit_target_info_arch (gcc_jit_target_info *info);
++
++extern int
++gcc_jit_target_info_supports_128bit_int (gcc_jit_target_info *info);
++
+/* Given type "T", get type "T __attribute__ ((packed))". */
+extern void
+gcc_jit_type_set_packed (gcc_jit_type *type);
@@ -3302,6 +4740,9 @@ index b3c389e93f6..f5537adbc91 100644
+ GCC_JIT_FN_ATTRIBUTE_TARGET,
+ GCC_JIT_FN_ATTRIBUTE_USED,
+ GCC_JIT_FN_ATTRIBUTE_VISIBILITY,
++ GCC_JIT_FN_ATTRIBUTE_COLD,
++ GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE,
++ GCC_JIT_FN_ATTRIBUTE_PURE,
+};
+
+/* Add an attribute to a function. */
@@ -3327,10 +4768,10 @@ index b3c389e93f6..f5537adbc91 100644
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
-index cc22b2b414e..a10a85ceace 100644
+index cc22b2b414e..e52de0057a5 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
-@@ -271,3 +271,49 @@ LIBGCCJIT_ABI_24 {
+@@ -271,3 +271,58 @@ LIBGCCJIT_ABI_24 {
gcc_jit_lvalue_set_alignment;
gcc_jit_lvalue_get_alignment;
} LIBGCCJIT_ABI_23;
@@ -3380,6 +4821,15 @@ index cc22b2b414e..a10a85ceace 100644
+ gcc_jit_context_new_vector_access;
+ gcc_jit_set_global_personality_function_name;
+} LIBGCCJIT_ABI_31;
++
++LIBGCCJIT_ABI_33 {
++ global:
++ gcc_jit_context_get_target_info;
++ gcc_jit_target_info_release;
++ gcc_jit_target_info_cpu_supports;
++ gcc_jit_target_info_arch;
++ gcc_jit_target_info_supports_128bit_int;
++} LIBGCCJIT_ABI_32;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 80606076e78..988e14ae9bc 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -3394,6 +4844,252 @@ index 80606076e78..988e14ae9bc 100644
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
+diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
+index 3568dbb9d63..45a6b25b62b 100644
+--- a/gcc/testsuite/jit.dg/jit.exp
++++ b/gcc/testsuite/jit.dg/jit.exp
+@@ -895,8 +895,41 @@ proc jit-verify-assembler-output { args } {
+ pass "${asm_filename} output pattern test, ${dg-output-text}"
+ verbose "Passed test for output pattern ${dg-output-text}" 3
+ }
++}
++
++# Assuming that a .s file has been written out named
++# OUTPUT_FILENAME, check that the argument doesn't match
++# the output file.
++proc jit-verify-assembler-output-not { args } {
++ verbose "jit-verify-assembler: $args"
++
++ set dg-output-text [lindex $args 0]
++ verbose "dg-output-text: ${dg-output-text}"
+
++ upvar 2 name name
++ verbose "name: $name"
++
++ upvar 2 prog prog
++ verbose "prog: $prog"
++ set asm_filename [jit-get-output-filename $prog]
++ verbose " asm_filename: ${asm_filename}"
++
++ # Read the assembly file.
++ set f [open $asm_filename r]
++ set content [read $f]
++ close $f
++
++ # Verify that the assembly matches the regex.
++ if { [regexp ${dg-output-text} $content] } {
++ fail "${asm_filename} output pattern test, is ${content}, should match ${dg-output-text}"
++ verbose "Failed test for output pattern ${dg-output-text}" 3
++ } else {
++ pass "${asm_filename} output pattern test, ${dg-output-text}"
++ verbose "Passed test for output pattern ${dg-output-text}" 3
++ }
+ }
++
++
+ # Assuming that a .o file has been written out named
+ # OUTPUT_FILENAME, invoke the driver to try to turn it into
+ # an executable, and try to run the result.
+diff --git a/gcc/testsuite/jit.dg/test-cold-attribute.c b/gcc/testsuite/jit.dg/test-cold-attribute.c
+new file mode 100644
+index 00000000000..8dc7ec5a34b
+--- /dev/null
++++ b/gcc/testsuite/jit.dg/test-cold-attribute.c
+@@ -0,0 +1,54 @@
++/* { dg-do compile { target x86_64-*-* } } */
++
++#include
++#include
++
++#include "libgccjit.h"
++
++/* We don't want set_options() in harness.h to set -O2 to see that the cold
++ attribute affects the optimizations. */
++#define TEST_ESCHEWS_SET_OPTIONS
++static void set_options (gcc_jit_context *ctxt, const char *argv0)
++{
++ // Set "-O2".
++ gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2);
++}
++
++#define TEST_COMPILING_TO_FILE
++#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER
++#define OUTPUT_FILENAME "output-of-test-cold-attribute.c.s"
++#include "harness.h"
++
++void
++create_code (gcc_jit_context *ctxt, void *user_data)
++{
++ /* Let's try to inject the equivalent of:
++int
++__attribute__ ((cold))
++t()
++{
++ return -1;
++}
++
++ */
++ gcc_jit_type *int_type =
++ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
++
++ gcc_jit_function *func_t =
++ gcc_jit_context_new_function (ctxt, NULL,
++ GCC_JIT_FUNCTION_EXPORTED,
++ int_type,
++ "t",
++ 0, NULL,
++ 0);
++ gcc_jit_function_add_attribute(func_t, GCC_JIT_FN_ATTRIBUTE_COLD);
++ gcc_jit_block *block = gcc_jit_function_new_block (func_t, NULL);
++ gcc_jit_rvalue *ret = gcc_jit_context_new_rvalue_from_int (ctxt,
++ int_type,
++ -1);
++
++ gcc_jit_block_end_with_return (block, NULL, ret);
++}
++
++/* { dg-final { jit-verify-output-file-was-created "" } } */
++/* { dg-final { jit-verify-assembler-output "orl" } } */
+diff --git a/gcc/testsuite/jit.dg/test-pure-attribute.c b/gcc/testsuite/jit.dg/test-pure-attribute.c
+new file mode 100644
+index 00000000000..049c495faac
+--- /dev/null
++++ b/gcc/testsuite/jit.dg/test-pure-attribute.c
+@@ -0,0 +1,134 @@
++/* { dg-do compile { target x86_64-*-* } } */
++
++#include
++#include
++
++#include "libgccjit.h"
++
++/* We don't want set_options() in harness.h to set -O3 to see that the cold
++ attribute affects the optimizations. */
++#define TEST_ESCHEWS_SET_OPTIONS
++static void set_options (gcc_jit_context *ctxt, const char *argv0)
++{
++ // Set "-O3".
++ gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);
++}
++
++#define TEST_COMPILING_TO_FILE
++#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER
++#define OUTPUT_FILENAME "output-of-test-pure-attribute.c.s"
++#include "harness.h"
++
++void
++create_code (gcc_jit_context *ctxt, void *user_data)
++{
++ /* Let's try to inject the equivalent of:
++__attribute__ ((pure))
++int foo (int x);
++int xxx(void)
++{
++ int x = 45;
++ int sum = 0;
++
++ while (x >>= 1)
++ sum += foo (x) * 2;
++ return sum;
++}
++ */
++ gcc_jit_type *int_type =
++ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
++
++ /* Creating the `foo` function. */
++ gcc_jit_param *n =
++ gcc_jit_context_new_param (ctxt, NULL, int_type, "x");
++ gcc_jit_param *params[1] = {n};
++ gcc_jit_function *foo_func =
++ gcc_jit_context_new_function (ctxt, NULL,
++ GCC_JIT_FUNCTION_IMPORTED,
++ int_type,
++ "foo",
++ 1, params,
++ 0);
++ gcc_jit_function_add_attribute(foo_func, GCC_JIT_FN_ATTRIBUTE_PURE);
++
++ /* Creating the `xxx` function. */
++ gcc_jit_function *xxx_func =
++ gcc_jit_context_new_function (ctxt, NULL,
++ GCC_JIT_FUNCTION_EXPORTED,
++ int_type,
++ "xxx",
++ 0, NULL,
++ 0);
++
++ gcc_jit_block *block = gcc_jit_function_new_block (xxx_func, NULL);
++
++ /* Build locals: */
++ gcc_jit_lvalue *x =
++ gcc_jit_function_new_local (xxx_func, NULL, int_type, "x");
++ gcc_jit_lvalue *sum =
++ gcc_jit_function_new_local (xxx_func, NULL, int_type, "sum");
++
++ /* int x = 45 */
++ gcc_jit_block_add_assignment (
++ block, NULL,
++ x,
++ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 45));
++ /* int sum = 0 */
++ gcc_jit_block_add_assignment (
++ block, NULL,
++ sum,
++ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0));
++
++ /* while (x >>= 1) { sum += foo (x) * 2; } */
++ gcc_jit_block *loop_cond =
++ gcc_jit_function_new_block (xxx_func, "loop_cond");
++ gcc_jit_block *loop_body =
++ gcc_jit_function_new_block (xxx_func, "loop_body");
++ gcc_jit_block *after_loop =
++ gcc_jit_function_new_block (xxx_func, "after_loop");
++
++ gcc_jit_block_end_with_jump (block, NULL, loop_cond);
++
++
++ /* if (x >>= 1) */
++ /* Since gccjit doesn't (yet?) have support for `>>=` operator, we will decompose it into:
++ `if (x = x >> 1)` */
++ gcc_jit_block_add_assignment_op (
++ loop_cond, NULL,
++ x,
++ GCC_JIT_BINARY_OP_RSHIFT,
++ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1));
++ /* The condition itself */
++ gcc_jit_block_end_with_conditional (
++ loop_cond, NULL,
++ gcc_jit_context_new_comparison (
++ ctxt, NULL,
++ GCC_JIT_COMPARISON_NE,
++ gcc_jit_lvalue_as_rvalue (x),
++ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0)),
++ after_loop,
++ loop_body);
++
++ /* sum += foo (x) * 2; */
++ gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue(x);
++ gcc_jit_block_add_assignment_op (
++ loop_body, NULL,
++ x,
++ GCC_JIT_BINARY_OP_PLUS,
++ gcc_jit_context_new_binary_op (
++ ctxt, NULL,
++ GCC_JIT_BINARY_OP_MULT, int_type,
++ gcc_jit_context_new_call (ctxt, NULL, foo_func, 1, &arg),
++ gcc_jit_context_new_rvalue_from_int (
++ ctxt,
++ int_type,
++ 2)));
++ gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);
++
++ /* return sum; */
++ gcc_jit_block_end_with_return (after_loop, NULL, gcc_jit_lvalue_as_rvalue(sum));
++}
++
++/* { dg-final { jit-verify-output-file-was-created "" } } */
++/* Check that the loop was optimized away */
++/* { dg-final { jit-verify-assembler-output-not "jne" } } */
diff --git a/gcc/testsuite/jit.dg/test-target-builtins.c b/gcc/testsuite/jit.dg/test-target-builtins.c
new file mode 100644
index 00000000000..0ffb48e97f6