From 7d4692c36ff8d43d3b8ad11ba39e8c66178ac2ed Mon Sep 17 00:00:00 2001 From: Heath123 Date: Thu, 20 Jul 2023 16:35:39 +0100 Subject: [PATCH] Update patches --- patches/gcc-13.1.0-rustc-codegen-gcc.patch | 1956 ++++++++++++++++++-- 1 file changed, 1826 insertions(+), 130 deletions(-) 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