sh-elf-gcc/patches/gcc-13.1.0-rustc-codegen-gcc.patch

5117 lines
156 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 00000000000..5fab7cf772c
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,32 @@
+name: CI
+
+on:
+ - push
+ - pull_request
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install mpfr
+ run: sudo apt-get install gcc-10 libmpfr-dev libmpc-dev
+
+ - name: Build libgccjit
+ run: |
+ cd ..
+ ls
+ mkdir build install
+ cd build
+ ../gcc/configure --enable-host-shared --enable-languages=jit,c++ --disable-bootstrap --disable-multilib --prefix=$(pwd)/../install
+ make -j4
+
+ - uses: actions/upload-artifact@v2
+ 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
+<http://www.gnu.org/licenses/>. */
+
+#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
+++ b/gcc/config/i386/i386-builtins.cc
@@ -226,6 +226,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
+static void
+clear_builtin_types (void)
+{
+ for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
+ ix86_builtin_type_tab[i] = NULL;
+
+ for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
+ {
+ ix86_builtins[i] = NULL;
+ ix86_builtins_isa[i].set_and_not_built_p = true;
+ }
+
+ for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
+ ix86_builtin_func_type_tab[i] = NULL;
+}
+
tree get_ix86_builtin (enum ix86_builtins c)
{
return ix86_builtins[c];
@@ -1443,6 +1459,8 @@ ix86_init_builtins (void)
{
tree ftype, decl;
+ clear_builtin_types ();
+
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
+<http://www.gnu.org/licenses/>. */
+
+#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 <char *> (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
+<http://www.gnu.org/licenses/>. */
+
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+#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/dwarf2asm.cc b/gcc/dwarf2asm.cc
index 65b95fee243..e66cd30c1fe 100644
--- a/gcc/dwarf2asm.cc
+++ b/gcc/dwarf2asm.cc
@@ -1159,4 +1159,14 @@ dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
va_end (ap);
}
+void dwarf2asm_cc_finalize (void)
+{
+ if (indirect_pool)
+ {
+ indirect_pool->empty();
+ indirect_pool = NULL;
+ }
+ dw2_const_labelno = 0;
+}
+
#include "gt-dwarf2asm.h"
diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h
index 37a0a05e5bb..80695b3c6c8 100644
--- a/gcc/dwarf2asm.h
+++ b/gcc/dwarf2asm.h
@@ -86,6 +86,8 @@ extern const char *eh_data_format_name (int);
extern rtx dw2_force_const_mem (rtx, bool);
extern void dw2_output_indirect_constants (void);
+void dwarf2asm_cc_finalize (void);
+
/* These are currently unused. */
#if 0
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 1f39df3b1e2..61b711d4a52 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -1003,6 +1003,9 @@ dwarf2out_do_cfi_startproc (bool second)
if (targetm.asm_out.make_eh_symbol_indirect != NULL)
ref = targetm.asm_out.make_eh_symbol_indirect (ref, true);
else
+ // TODO: HERE: should not insert multiple times the same personality function.
+ // If we don't, we segfault later, possibly because we don't generate the info for the duplicates.
+ // I'm not sure why it's attempting to insert multiple times the same personality function.
ref = dw2_force_const_mem (ref, true);
}
diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index a11f72f606b..61603c37230 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -6191,8 +6191,13 @@ init_emit_once (void)
/* Don't use gen_rtx_CONST_INT here since gen_rtx_CONST_INT in this case
tries to use these variables. */
for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
- const_int_rtx[i + MAX_SAVED_CONST_INT] =
- gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i);
+ {
+ // Do not initialize twice the constants because there are used elsewhere
+ // and libgccjit execute this function twice.
+ if (const_int_rtx[i + MAX_SAVED_CONST_INT] == NULL)
+ const_int_rtx[i + MAX_SAVED_CONST_INT] =
+ gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i);
+ }
if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT
&& STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT)
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 15be1c8db99..7fa2c114cb2 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -13365,6 +13365,7 @@ const_vector_from_tree (tree exp)
tree
build_personality_function (const char *lang)
{
+ // TODO: rewrite by calling build_personality_function_with_name.
const char *unwind_and_version;
tree decl, type;
char *name;
@@ -13406,6 +13407,28 @@ build_personality_function (const char *lang)
return decl;
}
+tree
+build_personality_function_with_name (const char *name)
+{
+ tree decl, type;
+
+ type = build_function_type_list (unsigned_type_node,
+ integer_type_node, integer_type_node,
+ long_long_unsigned_type_node,
+ ptr_type_node, ptr_type_node, NULL_TREE);
+ decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ get_identifier (name), type);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+
+ /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
+ are the flags assigned by targetm.encode_section_info. */
+ SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+
+ return decl;
+}
+
/* 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
+++ b/gcc/jit/dummy-frontend.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "target.h"
#include "jit-playback.h"
#include "stor-layout.h"
#include "debug.h"
@@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "stringpool.h"
#include "attribs.h"
+#include "jit-recording.h"
+#include "print-tree.h"
#include <mpfr.h>
+#include <unordered_map>
+#include <string>
+
+using namespace gcc::jit;
/* Attribute handling. */
@@ -86,6 +93,10 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
ATTR_EXCL (NULL, false, false, false)
};
+hash_map<nofree_string_hash, tree> target_builtins{};
+std::unordered_map<std::string, recording::function_type*> target_function_types{};
+recording::context target_builtins_ctxt{NULL};
+
/* Table of machine-independent attributes supported in libgccjit. */
const struct attribute_spec jit_attribute_table[] =
{
@@ -146,6 +157,20 @@ const struct attribute_spec jit_format_attribute_table[] =
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
+char* jit_personality_func_name = NULL;
+static tree personality_decl;
+
+/* FIXME: This is a hack to preserve trees that we create from the
+ garbage collector. */
+
+static GTY (()) tree jit_gc_root;
+
+void
+jit_preserve_from_gc (tree t)
+{
+ jit_gc_root = tree_cons (NULL_TREE, t, jit_gc_root);
+}
+
/* Attribute handlers. */
/* Handle a "noreturn" attribute; arguments as in
@@ -507,12 +532,12 @@ struct GTY(()) lang_identifier
/* The resulting tree type. */
union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
-lang_tree_node
-{
- union tree_node GTY((tag ("0"),
- desc ("tree_node_structure (&%h)"))) generic;
- struct lang_identifier GTY((tag ("1"))) identifier;
+ chain_next ("(union lang_tree_node *) jit_tree_chain_next (&%h.generic)"))) lang_tree_node
+ {
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
+ generic;
+ struct lang_identifier GTY ((tag ("1"))) identifier;
};
/* We don't use language_function. */
@@ -578,6 +603,8 @@ jit_end_diagnostic (diagnostic_context *context,
static bool
jit_langhook_init (void)
{
+ jit_gc_root = NULL_TREE;
+ personality_decl = NULL_TREE;
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
@@ -592,15 +619,25 @@ jit_langhook_init (void)
global_dc->begin_diagnostic = jit_begin_diagnostic;
global_dc->end_diagnostic = jit_end_diagnostic;
- build_common_tree_nodes (false);
+ build_common_tree_nodes (flag_signed_char);
+
+ /* I don't know why this has to be done explicitly. */
+ void_list_node = build_tree_list (NULL_TREE, void_type_node);
+ target_builtins.empty ();
build_common_builtin_nodes ();
+ /* Initialize EH, if we've been told to do so. */
+ if (flag_exceptions)
+ using_eh_for_cleanups ();
+
/* The default precision for floating point numbers. This is used
for floating point constants with abstract type. This may
eventually be controllable by a command line option. */
mpfr_set_default_prec (256);
+ targetm.init_builtins ();
+
return true;
}
@@ -668,11 +705,216 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
return NULL;
}
-/* Record a builtin function. We just ignore builtin functions. */
+recording::type* tree_type_to_jit_type (tree type)
+{
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
+ long constant_size = size.to_constant();
+ if (element_type != NULL)
+ return element_type->get_vector (constant_size);
+ return NULL;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ // For __builtin_ms_va_start.
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
+ }
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ // For __builtin_sysv_va_copy.
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
+ }
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ if (type == FLOATN_NX_TYPE_NODE (i))
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
+ }
+ }
+ if (type == void_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID);
+ }
+ else if (type == ptr_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID_PTR);
+ }
+ else if (type == const_ptr_type_node)
+ {
+ // Void const ptr.
+ recording::type* result = new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID_PTR);
+ return new recording::memento_of_get_const (result);
+ }
+ else if (type == unsigned_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
+ }
+ else if (type == long_unsigned_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_LONG);
+ }
+ else if (type == integer_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_INT);
+ }
+ else if (type == long_integer_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG);
+ }
+ else if (type == long_long_integer_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG_LONG);
+ }
+ else if (type == signed_char_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SIGNED_CHAR);
+ }
+ else if (type == char_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_CHAR);
+ }
+ else if (type == unsigned_intQI_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UINT8_T);
+ }
+ else if (type == short_integer_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SHORT);
+ }
+ else if (type == short_unsigned_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_SHORT);
+ }
+ else if (type == complex_float_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_FLOAT);
+ }
+ else if (type == complex_double_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_DOUBLE);
+ }
+ else if (type == complex_long_double_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
+ }
+ else if (type == float_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT);
+ }
+ else if (type == double_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_DOUBLE);
+ }
+ else if (type == long_double_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG_DOUBLE);
+ }
+ else if (type == bfloat16_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BFLOAT16);
+ }
+ else if (type == dfloat128_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
+ }
+ else if (type == long_long_unsigned_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ }
+ else if (type == boolean_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BOOL);
+ }
+ else if (type == size_type_node)
+ {
+ return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SIZE_T);
+ }
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ return element_type->get_pointer();
+ }
+ else
+ {
+ // Attempt to find an unqualified type when the current type has qualifiers.
+ tree tp = TYPE_MAIN_VARIANT (type);
+ for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
+ {
+ if (TYPE_QUALS (tp) == 0 && type != tp)
+ {
+ recording::type* result = tree_type_to_jit_type (tp);
+ if (result != NULL)
+ {
+ if (TYPE_READONLY (tp))
+ result = new recording::memento_of_get_const (result);
+ if (TYPE_VOLATILE (tp))
+ result = new recording::memento_of_get_volatile (result);
+ return result;
+ }
+ }
+ }
+
+ fprintf (stderr, "Unknown type:\n");
+ debug_tree (type);
+ abort ();
+ }
+
+ return NULL;
+}
+
+/* Record a builtin function. We save their types to be able to check types
+ in recording and for reflection. */
static tree
jit_langhook_builtin_function (tree decl)
{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ target_builtins.put (name, decl);
+
+ std::string string_name(name);
+ if (target_function_types.count (string_name) == 0)
+ {
+ tree function_type = TREE_TYPE (decl);
+ tree arg = TYPE_ARG_TYPES (function_type);
+ bool is_variadic = false;
+
+ auto_vec <recording::type *> param_types;
+
+ while (arg != void_list_node)
+ {
+ if (arg == NULL)
+ {
+ is_variadic = true;
+ break;
+ }
+ if (arg != void_list_node)
+ {
+ recording::type* arg_type = tree_type_to_jit_type(TREE_VALUE (arg));
+ if (arg_type == NULL)
+ return decl;
+ param_types.safe_push (arg_type);
+ }
+ arg = TREE_CHAIN (arg);
+ }
+
+ tree result_type = TREE_TYPE (function_type);
+ recording::type* return_type = tree_type_to_jit_type(result_type);
+
+ if (return_type == NULL)
+ return decl;
+
+ recording::function_type* func_type = new recording::function_type (&target_builtins_ctxt, return_type, param_types.length (),
+ param_types.address (), is_variadic, false);
+
+ target_function_types[string_name] = func_type;
+ }
+ }
return decl;
}
@@ -694,6 +936,25 @@ jit_langhook_getdecls (void)
return NULL;
}
+static tree
+jit_langhook_eh_personality (void)
+{
+ if (personality_decl == NULL_TREE)
+ {
+ if (jit_personality_func_name != NULL) {
+ personality_decl = build_personality_function_with_name (jit_personality_func_name);
+ jit_preserve_from_gc(personality_decl);
+ }
+ else {
+ return lhd_gcc_personality();
+ }
+ }
+ return personality_decl;
+}
+
+#undef LANG_HOOKS_EH_PERSONALITY
+#define LANG_HOOKS_EH_PERSONALITY jit_langhook_eh_personality
+
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "libgccjit"
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index fb86c77d0fe..622a061ea89 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
param_types.length (),
params,
func_type->is_variadic (),
- builtin_id);
+ builtin_id,
+ false);
delete[] params;
/* PR/64020 - If the client code is using builtin cos or sin,
@@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
result = m_ctxt->new_function_type (return_type,
num_args,
param_types,
- is_variadic);
+ is_variadic,
+ false);
error:
delete[] param_types;
@@ -609,6 +611,9 @@ builtins_manager::ensure_optimization_builtins_exist ()
We can't loop through all of the builtin_data array, we don't
support all types yet. */
(void)get_builtin_function_by_id (BUILT_IN_TRAP);
+ (void)get_builtin_function_by_id (BUILT_IN_POPCOUNT);
+ (void)get_builtin_function_by_id (BUILT_IN_POPCOUNTL);
+ (void)get_builtin_function_by_id (BUILT_IN_POPCOUNTLL);
}
/* Playback support. */
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 3ff7447fbf3..5c323411ea9 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#endif
-const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
+const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_BFLOAT16 + 1;
/* This comment is included by the docs.
@@ -93,6 +93,20 @@ const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
End of comment for inclusion in the docs. */
+static inline tree
+jit_tree_chain_next (tree t)
+{
+ /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different
+ kind of object, never a long chain of nodes. Prefer
+ TYPE_NEXT_VARIANT for types. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON))
+ return TYPE_NEXT_VARIANT (t);
+ /* Otherwise, if there is TREE_CHAIN, return it. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
+ return TREE_CHAIN (t);
+ return NULL;
+}
+
namespace gcc {
namespace jit {
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
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
#include "config.h"
#define INCLUDE_MUTEX
+#include "libgccjit.h"
#include "system.h"
#include "coretypes.h"
#include "target.h"
@@ -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;
+ case GCC_JIT_TYPE_BFLOAT16:
+ return bfloat16_type_node;
case GCC_JIT_TYPE_DOUBLE:
return double_type_node;
case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -326,7 +330,7 @@ playback::type *
playback::context::
new_array_type (playback::location *loc,
playback::type *element_type,
- int num_elements)
+ unsigned long num_elements)
{
gcc_assert (element_type);
@@ -407,7 +411,8 @@ playback::compound_type *
playback::context::
new_compound_type (location *loc,
const char *name,
- bool is_struct) /* else is union */
+ bool is_struct, /* else is union */
+ bool is_packed)
{
gcc_assert (name);
@@ -417,6 +422,9 @@ new_compound_type (location *loc,
TYPE_NAME (t) = get_identifier (name);
TYPE_SIZE (t) = 0;
+ if (is_packed)
+ TYPE_PACKED (t) = 1;
+
if (loc)
set_tree_location (t, loc);
@@ -424,7 +432,7 @@ new_compound_type (location *loc,
}
void
-playback::compound_type::set_fields (const auto_vec<playback::field *> *fields)
+playback::compound_type::set_fields (const auto_vec<playback::field *> *fields, bool is_packed)
{
/* Compare with c/c-decl.cc: finish_struct. */
tree t = as_tree ();
@@ -441,6 +449,10 @@ playback::compound_type::set_fields (const auto_vec<playback::field *> *fields)
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
}
+
+ if (is_packed && (DECL_BIT_FIELD (x)
+ || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+ DECL_PACKED (x) = 1;
fieldlist = chainon (x, fieldlist);
}
fieldlist = nreverse (fieldlist);
@@ -499,6 +511,40 @@ new_param (location *loc,
return new param (this, inner);
}
+const char* fn_attribute_to_string(gcc_jit_fn_attribute attr)
+{
+ switch (attr)
+ {
+ case GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE:
+ return "always_inline";
+ case GCC_JIT_FN_ATTRIBUTE_INLINE:
+ return NULL;
+ case GCC_JIT_FN_ATTRIBUTE_NOINLINE:
+ return "noinline";
+ case GCC_JIT_FN_ATTRIBUTE_TARGET:
+ return "target";
+ case GCC_JIT_FN_ATTRIBUTE_USED:
+ 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;
+}
+
+const char* variable_attribute_to_string(gcc_jit_variable_attribute attr)
+{
+ switch (attr)
+ {
+ case GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY:
+ return "visibility";
+ }
+ return NULL;
+}
+
/* Construct a playback::function instance. */
playback::function *
@@ -509,7 +555,10 @@ new_function (location *loc,
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ const std::vector<gcc_jit_fn_attribute> &attributes,
+ const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes,
+ int is_target_builtin)
{
int i;
param *param;
@@ -532,6 +581,7 @@ new_function (location *loc,
/* FIXME: this uses input_location: */
tree fndecl = build_fn_decl (name, fn_type);
+ TREE_NOTHROW (fndecl) = 0;
if (loc)
set_tree_location (fndecl, loc);
@@ -543,6 +593,14 @@ new_function (location *loc,
DECL_RESULT (fndecl) = resdecl;
DECL_CONTEXT (resdecl) = fndecl;
+ if (is_target_builtin)
+ {
+ tree *decl = target_builtins.get(name);
+ if (decl != NULL)
+ fndecl = *decl;
+ else
+ add_error (loc, "cannot find target builtin %s", name);
+ }
if (builtin_id)
{
gcc_assert (loc == NULL);
@@ -594,6 +652,58 @@ new_function (location *loc,
DECL_ATTRIBUTES (fndecl));
}
+ for (auto attr: attributes)
+ {
+ if (attr == GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE)
+ {
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+ }
+ else if (attr == GCC_JIT_FN_ATTRIBUTE_INLINE)
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ else if (attr == GCC_JIT_FN_ATTRIBUTE_NOINLINE)
+ DECL_UNINLINABLE (fndecl) = 1;
+ /* See handle_used_attribute in gcc/c-family/c-attribs.cc. */
+ else if (attr == GCC_JIT_FN_ATTRIBUTE_USED)
+ {
+ 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)
+ {
+ tree ident = get_identifier (attribute);
+ DECL_ATTRIBUTES (fndecl) =
+ tree_cons (ident, NULL_TREE, DECL_ATTRIBUTES (fndecl));
+ }
+ }
+
+ for (auto attr: string_attributes)
+ {
+ gcc_jit_fn_attribute& name = std::get<0>(attr);
+ std::string& value = std::get<1>(attr);
+ tree attribute_value = build_tree_list (NULL_TREE, ::build_string (value.length () + 1, value.c_str ()));
+ const char* attribute = fn_attribute_to_string (name);
+ tree ident = attribute ? get_identifier (attribute) : NULL;
+
+ /* See handle_target_attribute in gcc/c-family/c-attribs.cc. */
+ if (name == GCC_JIT_FN_ATTRIBUTE_TARGET)
+ /* We need to call valid_attribute_p so that the hook set-up some internal options. */
+ if (!ident || !targetm.target_option.valid_attribute_p (fndecl, ident, attribute_value, 0))
+ continue;
+
+ if (ident)
+ DECL_ATTRIBUTES (fndecl) =
+ tree_cons (ident, attribute_value, DECL_ATTRIBUTES (fndecl));
+ }
+
function *func = new function (this, fndecl, kind);
m_functions.safe_push (func);
return func;
@@ -607,7 +717,9 @@ global_new_decl (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name,
- enum global_var_flags flags)
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes)
{
gcc_assert (type);
gcc_assert (name);
@@ -646,15 +758,33 @@ global_new_decl (location *loc,
break;
}
- if (TYPE_READONLY (type_tree))
+ if (TYPE_READONLY (type_tree) || readonly)
TREE_READONLY (inner) = 1;
if (loc)
set_tree_location (inner, loc);
+ set_variable_attribute (attributes, inner);
+
return inner;
}
+void
+playback::
+set_variable_attribute(const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes, tree decl)
+{
+ for (auto attr: attributes)
+ {
+ gcc_jit_variable_attribute& name = std::get<0>(attr);
+ std::string& value = std::get<1>(attr);
+ tree attribute_value = build_tree_list (NULL_TREE, ::build_string (value.length () + 1, value.c_str ()));
+ tree ident = get_identifier (variable_attribute_to_string (name));
+
+ DECL_ATTRIBUTES (decl) =
+ tree_cons (ident, attribute_value, DECL_ATTRIBUTES (decl));
+ }
+}
+
/* In use by new_global and new_global_initialized. */
playback::lvalue *
@@ -674,10 +804,12 @@ new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name,
- enum global_var_flags flags)
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes)
{
tree inner =
- global_new_decl (loc, kind, type, name, flags);
+ global_new_decl (loc, kind, type, name, flags, readonly, attributes);
return global_finalize_lvalue (inner);
}
@@ -822,9 +954,11 @@ new_global_initialized (location *loc,
size_t initializer_num_elem,
const void *initializer,
const char *name,
- enum global_var_flags flags)
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes)
{
- tree inner = global_new_decl (loc, kind, type, name, flags);
+ tree inner = global_new_decl (loc, kind, type, name, flags, readonly, attributes);
vec<constructor_elt, va_gc> *constructor_elements = NULL;
@@ -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 ());
- tree t_ctor = build_constructor (type->as_tree (), v);
+ tree t_ctor;
+ t_ctor = build_constructor (type->as_tree (), v);
return new rvalue (this, t_ctor);
}
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ vector perm. */
+
+playback::rvalue *
+playback::context::new_rvalue_vector_perm (location *loc,
+ rvalue* elements1,
+ rvalue* elements2,
+ rvalue* mask)
+{
+ tree t_elements1 = elements1->as_tree ();
+ tree t_elements2 = elements2->as_tree ();
+ tree t_mask = mask->as_tree ();
+
+ tree t_vector_perm = build3 (VEC_PERM_EXPR, TREE_TYPE (t_elements1), t_elements1, t_elements2, t_mask);
+ if (loc)
+ set_tree_location (t_vector_perm, loc);
+ return new rvalue (this, t_vector_perm);
+}
+
/* Coerce a tree expression into a boolean tree expression. */
tree
@@ -1527,6 +1681,163 @@ new_array_access (location *loc,
}
}
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ vector conversion. */
+
+playback::rvalue *
+playback::context::
+convert_vector (location *loc,
+ rvalue *vector,
+ type *type)
+{
+ gcc_assert (vector);
+ gcc_assert (type);
+
+ /* For comparison, see:
+ c/c-common.cc: c_build_vec_convert
+ */
+
+ tree t_vector = vector->as_tree ();
+
+ /* It seems IFN_VEC_CONVERT only work on registers, not on memory. */
+ if (TREE_CODE (t_vector) == VAR_DECL)
+ DECL_REGISTER (t_vector) = 1;
+ tree t_result = build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_VEC_CONVERT, type->as_tree (), 1, t_vector);
+
+ if (loc)
+ set_tree_location (t_result, loc);
+
+ return new rvalue (this, t_result);
+}
+
+/* The following functions come from c-common.h. */
+/* Like c_mark_addressable but don't check register qualifier. */
+void
+common_mark_addressable_vec (tree t)
+{
+ while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR)
+ {
+ t = TREE_OPERAND (t, 0);
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != COMPOUND_LITERAL_EXPR
+ && TREE_CODE (t) != TARGET_EXPR)
+ return;
+ if (!VAR_P (t) || !DECL_HARD_REGISTER (t))
+ TREE_ADDRESSABLE (t) = 1;
+ if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+ TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
+ else if (TREE_CODE (t) == TARGET_EXPR)
+ TREE_ADDRESSABLE (TARGET_EXPR_SLOT (t)) = 1;
+}
+
+/* Return true if TYPE is a vector type that should be subject to the GNU
+ vector extensions (as opposed to a vector type that is used only for
+ the purposes of defining target-specific built-in functions). */
+
+inline bool
+gnu_vector_type_p (const_tree type)
+{
+ return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
+}
+
+/* Return nonzero if REF is an lvalue valid for this language.
+ Lvalues can be assigned, unless their type has TYPE_READONLY.
+ Lvalues can have their address taken, unless they have C_DECL_REGISTER. */
+
+bool
+lvalue_p (const_tree ref)
+{
+ const enum tree_code code = TREE_CODE (ref);
+
+ switch (code)
+ {
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case COMPONENT_REF:
+ return lvalue_p (TREE_OPERAND (ref, 0));
+
+ case C_MAYBE_CONST_EXPR:
+ return lvalue_p (TREE_OPERAND (ref, 1));
+
+ case COMPOUND_LITERAL_EXPR:
+ case STRING_CST:
+ return true;
+
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+ here as well. */
+ case INDIRECT_REF:
+ case ARRAY_REF:
+ case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case ERROR_MARK:
+ return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
+
+ case BIND_EXPR:
+ return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
+
+ default:
+ return false;
+ }
+}
+
+bool
+convert_vector_to_array_for_subscript (tree *vecp)
+{
+ bool ret = false;
+ if (gnu_vector_type_p (TREE_TYPE (*vecp)))
+ {
+ tree type = TREE_TYPE (*vecp);
+
+ ret = !lvalue_p (*vecp);
+
+ /* We are building an ARRAY_REF so mark the vector as addressable
+ to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P
+ for function parameters. */
+ // NOTE: that was the missing piece for making vector access work with optimizations enabled.
+ common_mark_addressable_vec (*vecp);
+
+ *vecp = build1 (VIEW_CONVERT_EXPR,
+ build_array_type_nelts (TREE_TYPE (type),
+ TYPE_VECTOR_SUBPARTS (type)),
+ *vecp);
+ }
+ return ret;
+}
+
+/* Construct a playback::lvalue instance (wrapping a tree) for a
+ vector access. */
+
+playback::lvalue *
+playback::context::
+new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index)
+{
+ gcc_assert (vector);
+ gcc_assert (index);
+
+ /* For comparison, see:
+ c/c-typeck.cc: build_array_ref
+ */
+
+ tree t_vector = vector->as_tree ();
+ bool non_lvalue = convert_vector_to_array_for_subscript (&t_vector);
+ tree type = TREE_TYPE (TREE_TYPE (t_vector));
+ tree t_result = build4 (ARRAY_REF, type, t_vector, index->as_tree (), NULL_TREE, NULL_TREE);
+ if (non_lvalue)
+ t_result = non_lvalue (t_result);
+
+ if (loc)
+ set_tree_location (t_result, loc);
+ return new lvalue (this, t_result);
+}
+
/* Construct a tree for a field access. */
tree
@@ -1812,7 +2123,8 @@ playback::lvalue *
playback::function::
new_local (location *loc,
type *type,
- const char *name)
+ const char *name,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes)
{
gcc_assert (type);
gcc_assert (name);
@@ -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;
+ set_variable_attribute (attributes, inner);
+
if (loc)
set_tree_location (inner, loc);
return new lvalue (m_ctxt, inner);
@@ -1857,6 +2171,15 @@ playback::function::get_address (location *loc)
return new rvalue (m_ctxt, t_fnptr);
}
+/* Construct a new local within this playback::function. */
+
+void
+playback::function::
+set_personality_function (function *personality_function)
+{
+ DECL_FUNCTION_PERSONALITY (m_inner_fndecl) = personality_function->as_fndecl ();
+}
+
/* 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 +2198,11 @@ build_stmt_list ()
int j;
tree stmt;
+ // Do not add try/catch block to the function.
+ // TODO: explain why.
+ if (b->m_is_try_or_catch)
+ continue;
+
b->m_label_expr = build1 (LABEL_EXPR,
void_type_node,
b->as_label_decl ());
@@ -1973,6 +2301,70 @@ add_eval (location *loc,
add_stmt (rvalue->as_tree ());
}
+
+void
+playback::block::
+add_try_catch (location *loc,
+ block *try_block,
+ block *catch_block,
+ bool is_finally)
+{
+ gcc_assert (try_block);
+ gcc_assert (catch_block);
+
+ try_block->m_is_try_or_catch = true;
+ catch_block->m_is_try_or_catch = true;
+
+ if (loc)
+ {
+ set_tree_location (try_block->as_label_decl (), loc);
+ set_tree_location (catch_block->as_label_decl (), loc);
+ }
+
+ tree try_body = alloc_stmt_list ();
+ unsigned int i;
+ tree stmt;
+ FOR_EACH_VEC_ELT (try_block->m_stmts, i, stmt) {
+ append_to_statement_list (stmt, &try_body);
+ }
+
+ tree catch_body = alloc_stmt_list ();
+ unsigned int j;
+ tree catch_stmt;
+ FOR_EACH_VEC_ELT (catch_block->m_stmts, j, catch_stmt) {
+ append_to_statement_list (catch_stmt, &catch_body);
+ }
+
+ if (is_finally)
+ {
+ tree success_body = alloc_stmt_list ();
+
+ // TODO: find a better way to keep the EH_ELSE_EXPR than creating an empty inline asm.
+ tree t_string = build_string ("");
+ tree asm_stmt
+ = build5 (ASM_EXPR, void_type_node, t_string, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
+
+ // asm statements without outputs, including simple ones, are treated
+ // as volatile.
+ ASM_VOLATILE_P (asm_stmt) = 1;
+ ASM_INPUT_P (asm_stmt) = 0;
+ append_to_statement_list (asm_stmt, &success_body);
+
+ // TODO: Don't automatically add the `EH_ELSE_EXPR`. Make an API to create such a node and let the user of libgccjit
+ // add it manually.
+ catch_body = build2 (EH_ELSE_EXPR, void_type_node, success_body, catch_body);
+ add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
+ try_body, catch_body));
+ }
+ else
+ {
+ catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body);
+ tree try_catch = build2 (TRY_CATCH_EXPR, void_type_node,
+ try_body, catch_body);
+ add_stmt (try_catch);
+ }
+}
+
/* 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..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
#ifndef JIT_PLAYBACK_H
#define JIT_PLAYBACK_H
+#include <string>
#include <utility> // for std::pair
+#include <vector>
#include "timevar.h"
#include "varasm.h"
@@ -41,11 +43,15 @@ namespace jit {
namespace playback {
+void
+set_variable_attribute(const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes, tree decl);
+
/* playback::context is an abstract base class.
- 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,
- int num_elements);
+ unsigned long num_elements);
field *
new_field (location *loc,
@@ -85,7 +91,8 @@ public:
compound_type *
new_compound_type (location *loc,
const char *name,
- bool is_struct); /* else is union */
+ bool is_struct, /* else is union */
+ bool is_packed);
type *
new_function_type (type *return_type,
@@ -104,14 +111,19 @@ public:
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ const std::vector<gcc_jit_fn_attribute> &attributes,
+ const std::vector<std::pair<gcc_jit_fn_attribute, std::string>> &string_attributes,
+ int is_target_builtin);
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name,
- enum global_var_flags flags);
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes);
lvalue *
new_global_initialized (location *loc,
@@ -121,7 +133,9 @@ public:
size_t initializer_num_elem,
const void *initializer,
const char *name,
- enum global_var_flags flags);
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes);
rvalue *
new_ctor (location *log,
@@ -147,6 +161,12 @@ public:
type *type,
const auto_vec<rvalue *> &elements);
+ rvalue *
+ new_rvalue_vector_perm (location *loc,
+ rvalue* elements1,
+ rvalue* elements2,
+ rvalue* mask);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
@@ -191,6 +211,16 @@ public:
rvalue *ptr,
rvalue *index);
+ rvalue *
+ convert_vector (location *loc,
+ rvalue *vector,
+ type *type);
+
+ lvalue *
+ new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index);
+
void
set_str_option (enum gcc_jit_str_option opt,
const char *value);
@@ -306,7 +336,9 @@ private:
enum gcc_jit_global_kind kind,
type *type,
const char *name,
- enum global_var_flags flags);
+ enum global_var_flags flags,
+ bool readonly,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes);
lvalue *
global_finalize_lvalue (tree inner);
@@ -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)
{}
- void set_fields (const auto_vec<field *> *fields);
+ void set_fields (const auto_vec<field *> *fields, bool is_packed);
};
class field : public wrapper
@@ -495,7 +539,8 @@ public:
lvalue *
new_local (location *loc,
type *type,
- const char *name);
+ const char *name,
+ const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes);
block*
new_block (const char *name);
@@ -503,6 +548,9 @@ public:
rvalue *
get_address (location *loc);
+ void
+ set_personality_function (function *personality_function);
+
void
build_stmt_list ();
@@ -573,6 +621,12 @@ public:
add_eval (location *loc,
rvalue *rvalue);
+ void
+ add_try_catch (location *loc,
+ block *try_block,
+ block *catch_block,
+ bool is_finally);
+
void
add_assignment (location *loc,
lvalue *lvalue,
@@ -636,6 +690,7 @@ private:
public: // for now
tree m_label_expr;
+ bool m_is_try_or_catch = false;
friend class function;
};
@@ -813,4 +868,6 @@ extern playback::context *active_playback_ctxt;
} // namespace gcc
+extern hash_map<nofree_string_hash, tree> target_builtins;
+
#endif /* JIT_PLAYBACK_H */
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
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)
recording::type *
recording::context::new_array_type (recording::location *loc,
recording::type *element_type,
- int num_elements)
+ unsigned long num_elements)
{
- if (struct_ *s = element_type->dyn_cast_struct ())
+ /*if (struct_ *s = element_type->dyn_cast_struct ())
if (!s->get_fields ())
{
add_error (NULL,
@@ -850,7 +850,7 @@ recording::context::new_array_type (recording::location *loc,
" until the fields have been set",
s->get_name ()->c_str ());
return NULL;
- }
+ }*/
recording::type *result =
new recording::array_type (this, loc, element_type, num_elements);
record (result);
@@ -933,14 +933,16 @@ recording::function_type *
recording::context::new_function_type (recording::type *return_type,
int num_params,
recording::type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
{
recording::function_type *fn_type
= new function_type (this,
return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ is_target_builtin);
record (fn_type);
return fn_type;
}
@@ -962,7 +964,8 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc
= new_function_type (return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ false);
/* Return a pointer-type to the function type. */
return fn_type->get_pointer ();
@@ -1005,7 +1008,7 @@ recording::context::new_function (recording::location *loc,
loc, kind, return_type,
new_string (name),
num_params, params, is_variadic,
- builtin_id);
+ builtin_id, false);
record (result);
m_functions.safe_push (result);
@@ -1044,6 +1047,52 @@ recording::context::get_builtin_function (const char *name)
return bm->get_builtin_function (name);
}
+/* Create a recording::function instance for a target-specific builtin.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_target_builtin_function. */
+
+recording::function *
+recording::context::get_target_builtin_function (const char *name)
+{
+ const char *asm_name = name;
+ if (target_function_types.count (name) == 0)
+ {
+ fprintf (stderr, "Cannot find target builtin %s\n", name);
+ return NULL;
+ }
+
+ recording::function_type* func_type = target_function_types[name]->copy (this)->dyn_cast_function_type ();
+ const vec<type *>& param_types = func_type->get_param_types ();
+ recording::param **params = new recording::param *[param_types.length ()];
+
+ int i;
+ recording::type *param_type;
+ FOR_EACH_VEC_ELT (param_types, i, param_type)
+ {
+ char buf[16];
+ snprintf (buf, 16, "arg%d", i);
+ params[i] = new_param (NULL,
+ param_type,
+ buf);
+ }
+
+ recording::function *result =
+ new recording::function (this,
+ NULL,
+ GCC_JIT_FUNCTION_IMPORTED, // FIXME
+ func_type->get_return_type (),
+ new_string (asm_name),
+ param_types.length (),
+ params,
+ func_type->is_variadic (),
+ BUILT_IN_NONE,
+ true);
+ record (result);
+
+ return result;
+}
+
/* Create a recording::global instance and add it to this context's list
of mementos.
@@ -1108,6 +1157,18 @@ recording::context::new_rvalue_from_vector (location *loc,
return result;
}
+recording::rvalue *
+recording::context::new_rvalue_vector_perm (location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask)
+{
+ recording::rvalue *result
+ = new memento_of_new_rvalue_vector_perm (this, loc, elements1, elements2, mask);
+ record (result);
+ return result;
+}
+
recording::rvalue *
recording::context::new_ctor (recording::location *loc,
recording::type *type,
@@ -1309,6 +1370,39 @@ recording::context::new_array_access (recording::location *loc,
return result;
}
+/* Create a recording::convert_vector instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_convert_vector. */
+
+recording::rvalue *
+recording::context::new_convert_vector (recording::location *loc,
+ recording::rvalue *vector,
+ recording::type *type)
+{
+ // TODO: instead have an "internal function" memento?
+ recording::rvalue *result = new convert_vector (this, loc, vector, type);
+ record (result);
+ return result;
+}
+
+/* Create a recording::vector_access instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_vector_access. */
+
+recording::lvalue *
+recording::context::new_vector_access (recording::location *loc,
+ recording::rvalue *vector,
+ recording::rvalue *index)
+{
+ recording::lvalue *result = new vector_access (this, loc, vector, index);
+ record (result);
+ return result;
+}
+
/* Create a recording::case_ instance and add it to this context's list
of mementos.
@@ -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;
}
+void
+recording::type::set_packed ()
+{
+ m_packed = true;
+}
+
/* Given a type, get a vector version of the type.
Implements the post-error-checking part of
@@ -2372,6 +2491,10 @@ recording::memento_of_get_type::get_size ()
case GCC_JIT_TYPE_FLOAT:
size = FLOAT_TYPE_SIZE;
break;
+ #ifdef HAVE_BFmode
+ case GCC_JIT_TYPE_BFLOAT16:
+ return GET_MODE_UNIT_SIZE (BFmode);
+ #endif
case GCC_JIT_TYPE_DOUBLE:
size = DOUBLE_TYPE_SIZE;
break;
@@ -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:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
case GCC_JIT_TYPE_COMPLEX_FLOAT:
@@ -2495,6 +2619,7 @@ recording::memento_of_get_type::is_int () const
return true;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
@@ -2553,6 +2678,7 @@ recording::memento_of_get_type::is_signed () const
case GCC_JIT_TYPE_UINT128_T:
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2612,6 +2738,7 @@ recording::memento_of_get_type::is_float () const
return false;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return true;
@@ -2675,6 +2802,7 @@ recording::memento_of_get_type::is_bool () const
return false;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
@@ -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 */
+ "bfloat16", /* GCC_JIT_TYPE_BFLOAT16 */
};
@@ -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",
+ "GCC_JIT_TYPE_BFLOAT16",
};
void
@@ -3066,7 +3196,7 @@ recording::string *
recording::array_type::make_debug_string ()
{
return string::from_printf (m_ctxt,
- "%s[%d]",
+ "%s[%ld]",
m_element_type->get_debug_string (),
m_num_elements);
}
@@ -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"
- " %i); /* int num_elements */\n",
+ " %li); /* int num_elements */\n",
id,
r.get_identifier (get_context ()),
r.get_identifier (m_loc),
@@ -3098,11 +3228,13 @@ recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
: type (ctxt),
m_return_type (return_type),
m_param_types (),
- m_is_variadic (is_variadic)
+ m_is_variadic (is_variadic),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
m_param_types.safe_push (param_types[i]);
@@ -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 (),
- true /* is_struct */));
+ true, /* is_struct */
+ m_packed));
}
const char *
@@ -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 (),
- false /* is_struct */));
+ false, /* is_struct */
+ m_packed));
}
/* Implementation of recording::memento::make_debug_string for
@@ -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 ());
- m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
+ m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields, m_struct_or_union->m_packed);
}
/* Override the default implementation of
@@ -3979,6 +4113,11 @@ void recording::lvalue::set_alignment (unsigned bytes)
m_alignment = bytes;
}
+void recording::lvalue::add_attribute (gcc_jit_variable_attribute attribute, const char* value)
+{
+ m_attributes.push_back (std::make_pair (attribute, std::string (value)));
+}
+
/* The implementation of class gcc::jit::recording::param. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -4044,7 +4183,8 @@ recording::function::function (context *ctxt,
int num_params,
recording::param **params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ int is_target_builtin)
: memento (ctxt),
m_loc (loc),
m_kind (kind),
@@ -4055,7 +4195,10 @@ recording::function::function (context *ctxt,
m_builtin_id (builtin_id),
m_locals (),
m_blocks (),
- m_fn_ptr_type (NULL)
+ m_fn_ptr_type (NULL),
+ m_attributes(),
+ m_string_attributes(),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
{
@@ -4114,7 +4257,40 @@ recording::function::replay_into (replayer *r)
m_name->c_str (),
&params,
m_is_variadic,
- m_builtin_id));
+ m_builtin_id,
+ m_attributes,
+ m_string_attributes,
+ m_is_target_builtin));
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ setting a personality function. */
+
+recording::string *
+recording::memento_of_set_personality_function::make_debug_string ()
+{
+ return string::from_printf (m_ctxt,
+ "%s",
+ m_personality_function->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for setting the personality function. */
+
+void
+recording::memento_of_set_personality_function::write_reproducer (reproducer &r)
+{
+ r.write (" gcc_jit_function_set_personality_function (%s,\n"
+ " %s);\n",
+ r.get_identifier (m_function),
+ r.get_identifier (m_personality_function));
+}
+
+void
+recording::function::set_personality_function (function *function)
+{
+ recording::memento_of_set_personality_function *result =
+ new memento_of_set_personality_function (m_ctxt, this, function);
+ m_ctxt->record (result);
}
/* Create a recording::local instance and add it to
@@ -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<block *> worklist (m_blocks.length ());
+ int j;
+ block *func_block;
+ /* Push the blocks used in try/catch because they're not successors of
+ other blocks. */
+ FOR_EACH_VEC_ELT (m_blocks, j, func_block)
+ if (func_block->m_is_reachable)
+ worklist.safe_push (func_block);
worklist.safe_push (m_blocks[0]);
while (worklist.length () > 0)
{
@@ -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 (),
- m_is_variadic);
+ m_is_variadic,
+ m_is_target_builtin);
m_fn_ptr_type = fn_type->get_pointer ();
}
gcc_assert (m_fn_ptr_type);
@@ -4357,6 +4541,18 @@ recording::function::get_address (recording::location *loc)
return result;
}
+void
+recording::function::add_attribute (gcc_jit_fn_attribute attribute)
+{
+ m_attributes.push_back (attribute);
+}
+
+void
+recording::function::add_string_attribute (gcc_jit_fn_attribute attribute, const char* value)
+{
+ m_string_attributes.push_back (std::make_pair (attribute, std::string (value)));
+}
+
/* Implementation of recording::memento::make_debug_string for
functions. */
@@ -4441,6 +4637,31 @@ recording::block::add_eval (recording::location *loc,
return result;
}
+/* The implementation of class gcc::jit::recording::block. */
+
+/* Create a recording::try_catch instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+ Implements the heart of gcc_jit_block_add_try_catch. */
+
+recording::statement *
+recording::block::add_try_catch (location *loc,
+ block *try_block,
+ block *catch_block,
+ bool is_finally)
+{
+ statement *result = new try_catch (this, loc, try_block, catch_block, is_finally);
+ // TODO: explain why we set the blocks reachable state.
+ try_block->m_is_reachable = true;
+ catch_block->m_is_reachable = true;
+ /* The finally block can fallthrough, so we don't require the user to terminate it. */
+ if (is_finally)
+ catch_block->m_has_been_terminated = true;
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ return result;
+}
+
/* 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 +5053,16 @@ recording::global::replay_into (replayer *r)
/ m_type->dereference ()->get_size (),
m_initializer,
playback_string (m_name),
- m_flags)
+ m_flags,
+ m_readonly,
+ m_attributes)
: r->new_global (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
playback_string (m_name),
- m_flags);
+ m_flags,
+ m_readonly,
+ m_attributes);
if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
global->set_tls_model (recording::tls_models[m_tls_model]);
@@ -5390,6 +5615,91 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
elements_id);
}
+/* The implementation of class
+ gcc::jit::recording::memento_of_new_rvalue_vector_perm. */
+
+/* The constructor for
+ gcc::jit::recording::memento_of_new_rvalue_vector_perm. */
+
+recording::memento_of_new_rvalue_vector_perm::
+memento_of_new_rvalue_vector_perm (context *ctxt,
+ location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask)
+: rvalue (ctxt, loc, elements1->get_type ()),
+ m_elements1 (elements1),
+ m_elements2 (elements2),
+ m_mask (mask)
+{
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_vector_perm. */
+
+void
+recording::memento_of_new_rvalue_vector_perm::replay_into (replayer *r)
+{
+ playback::rvalue *playback_elements1 = m_elements1->playback_rvalue ();
+ playback::rvalue *playback_elements2 = m_elements2->playback_rvalue ();
+ playback::rvalue *playback_mask = m_mask->playback_rvalue ();
+
+ set_playback_obj (r->new_rvalue_vector_perm (playback_location (r, m_loc),
+ playback_elements1,
+ playback_elements2,
+ playback_mask));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::memento_of_new_rvalue_from_vector. */
+
+ void
+recording::memento_of_new_rvalue_vector_perm::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_elements1);
+ v->visit (m_elements2);
+ v->visit (m_mask);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ vectors. */
+
+ recording::string *
+recording::memento_of_new_rvalue_vector_perm::make_debug_string ()
+{
+ /* Now build a string. */
+ string *result = string::from_printf (m_ctxt,
+ "shufflevector(%s, %s, %s)",
+ m_elements1->get_debug_string (),
+ m_elements2->get_debug_string (),
+ m_mask->get_debug_string ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vectors. */
+
+ void
+recording::memento_of_new_rvalue_vector_perm::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "vector");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_rvalue_vector_perm (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue **elements1*/\n"
+ " %s, /* gcc_jit_rvalue **elements2*/\n"
+ " %s); /* gcc_jit_rvalue **mask*/\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_elements1),
+ r.get_identifier_as_rvalue (m_elements2),
+ r.get_identifier_as_rvalue (m_mask));
+}
+
+
void
recording::ctor::visit_children (rvalue_visitor *v)
{
@@ -6260,6 +6570,114 @@ recording::array_access::write_reproducer (reproducer &r)
r.get_identifier_as_rvalue (m_index));
}
+/* The implementation of class gcc::jit::recording::convert_vector. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::convert_vector. */
+
+void
+recording::convert_vector::replay_into (replayer *r)
+{
+ set_playback_obj (
+ r->convert_vector (playback_location (r, m_loc),
+ m_vector->playback_rvalue (),
+ m_type->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::convert_vector. */
+
+void
+recording::convert_vector::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_vector);
+}
+
+/* The implementation of class gcc::jit::recording::vector_access. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::vector_access. */
+
+void
+recording::vector_access::replay_into (replayer *r)
+{
+ set_playback_obj (
+ r->new_vector_access (playback_location (r, m_loc),
+ m_vector->playback_rvalue (),
+ m_index->playback_rvalue ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::vector_access. */
+
+void
+recording::vector_access::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_vector);
+ v->visit (m_index);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ array accesses. */
+
+recording::string *
+recording::convert_vector::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "(%s)%s",
+ m_type->get_debug_string (),
+ m_vector->get_debug_string_parens (prec));
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ convert_vector. */
+
+void
+recording::convert_vector::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "lvalue");
+ r.write (" gcc_jit_lvalue *%s = \n"
+ " gcc_jit_context_convert_vector (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /*gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *vector */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_vector),
+ r.get_identifier_as_type (m_type));
+}
+
+recording::string *
+recording::vector_access::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "%s[%s]",
+ m_vector->get_debug_string_parens (prec),
+ m_index->get_debug_string_parens (prec));
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vector_access. */
+
+void
+recording::vector_access::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "lvalue");
+ r.write (" gcc_jit_lvalue *%s = \n"
+ " gcc_jit_context_new_vector_access (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /*gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *vector */\n"
+ " %s); /* gcc_jit_rvalue *index */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_vector),
+ r.get_identifier_as_rvalue (m_index));
+}
+
/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -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 (),
- playback_string (m_name));
+ playback_string (m_name),
+ m_attributes);
if (m_reg_name != NULL)
obj->set_register_name (m_reg_name->c_str ());
@@ -6649,6 +7068,17 @@ recording::statement::write_to_dump (dump &d)
m_loc = d.make_location ();
}
+/* The implementation of class gcc::jit::recording::memento_of_set_personality_function. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_set_personality_function. */
+
+void
+recording::memento_of_set_personality_function::replay_into (replayer *r)
+{
+ m_function->playback_function ()->set_personality_function (m_personality_function->playback_function ());
+}
+
/* The implementation of class gcc::jit::recording::eval. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -6687,6 +7117,59 @@ recording::eval::write_reproducer (reproducer &r)
r.get_identifier_as_rvalue (m_rvalue));
}
+/* The implementation of class gcc::jit::recording::try_catch. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::try_catch. */
+
+void
+recording::try_catch::replay_into (replayer *r)
+{
+ playback_block (get_block ())
+ ->add_try_catch (playback_location (r),
+ m_try_block->playback_block (),
+ m_catch_block->playback_block (),
+ m_is_finally);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ an eval statement. */
+
+recording::string *
+recording::try_catch::make_debug_string ()
+{
+ if (m_is_finally)
+ return string::from_printf (m_ctxt,
+ "try { %s } finally { %s };",
+ m_try_block->get_debug_string (),
+ m_catch_block->get_debug_string ());
+ else
+ return string::from_printf (m_ctxt,
+ "try { %s } catch { %s };",
+ m_try_block->get_debug_string (),
+ m_catch_block->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ eval statements. */
+
+void
+recording::try_catch::write_reproducer (reproducer &r)
+{
+ const char *func_name = "gcc_jit_block_add_try_catch";
+ if (m_is_finally)
+ func_name = "gcc_jit_block_add_try_finally";
+ r.write (" %s (%s, /*gcc_jit_block *block */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_block *try_block */\n"
+ " %s); /* gcc_jit_block *catch_block */\n",
+ func_name,
+ r.get_identifier (get_block ()),
+ r.get_identifier (get_loc ()),
+ r.get_identifier (m_try_block),
+ r.get_identifier (m_catch_block));
+}
+
/* The implementation of class gcc::jit::recording::assignment. */
/* 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..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
#include "jit-common.h"
#include "jit-logging.h"
+#include "libgccjit.h"
+
+#include <string>
+#include <vector>
+
+#include <string>
+#include <unordered_map>
class timer;
+extern std::unordered_map<std::string, gcc::jit::recording::function_type*> target_function_types;
+
namespace gcc {
namespace jit {
-
extern const char * const unary_op_reproducer_strings[];
extern const char * const binary_op_reproducer_strings[];
@@ -91,7 +99,7 @@ public:
type *
new_array_type (location *loc,
type *element_type,
- int num_elements);
+ unsigned long num_elements);
field *
new_field (location *loc,
@@ -116,7 +124,8 @@ public:
new_function_type (type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *
new_function_ptr_type (location *loc,
@@ -143,6 +152,9 @@ public:
function *
get_builtin_function (const char *name);
+ function *
+ get_target_builtin_function (const char *name);
+
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
@@ -173,6 +185,12 @@ public:
vector_type *type,
rvalue **elements);
+ rvalue *
+ new_rvalue_vector_perm (location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
@@ -215,6 +233,16 @@ public:
rvalue *ptr,
rvalue *index);
+ rvalue *
+ new_convert_vector (location *loc,
+ rvalue *vector,
+ type *type);
+
+ lvalue *
+ new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index);
+
case_ *
new_case (rvalue *min_value,
rvalue *max_value,
@@ -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);
+ void set_packed ();
+
/* Get the type obtained when dereferencing this type.
This will return NULL if it's not valid to dereference this type.
@@ -539,6 +572,8 @@ public:
these types. */
virtual size_t get_size () { gcc_unreachable (); }
+ virtual type* copy(context* ctxt) = 0;
+
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
@@ -593,9 +628,13 @@ public:
protected:
type (context *ctxt)
: memento (ctxt),
+ m_packed (false),
m_pointer_to_this_type (NULL)
{}
+public:
+ bool m_packed;
+
private:
type *m_pointer_to_this_type;
};
@@ -613,6 +652,11 @@ public:
size_t get_size () final override;
+ type* copy(context* ctxt) final override
+ {
+ return ctxt->get_type (m_kind);
+ }
+
bool accepts_writes_from (type *rtype) final override
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
@@ -664,6 +708,13 @@ public:
type *dereference () final override { return m_other_type; }
+ type* copy(context* ctxt) final override
+ {
+ type* result = new memento_of_get_pointer (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_size () final override;
bool accepts_writes_from (type *rtype) final override;
@@ -699,6 +750,7 @@ public:
size_t get_size () final override { return m_other_type->get_size (); };
+ // FIXME: this is wrong. A vector is not an int.
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 +770,11 @@ public:
memento_of_get_const (type *other_type)
: decorated_type (other_type) {}
- bool accepts_writes_from (type */*rtype*/) final override
+ type* copy(context* ctxt) final override
{
- /* Can't write to a "const". */
- return false;
+ type* result = new memento_of_get_const (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
}
/* Strip off the "const", giving the underlying type. */
@@ -757,6 +810,13 @@ public:
return m_other_type->is_same_type_as (other->is_volatile ());
}
+ type* copy(context* ctxt) final override
+ {
+ type* result = new memento_of_get_volatile (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -777,11 +837,20 @@ public:
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
+ type* copy(context* ctxt) final override
+ {
+ type* result = new memento_of_get_aligned (m_other_type->copy (ctxt), m_alignment_in_bytes);
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the alignment, giving the underlying type. */
type *unqualified () final override { return m_other_type; }
void replay_into (replayer *) final override;
+ vector_type *dyn_cast_vector_type () final override { return m_other_type->dyn_cast_vector_type (); }
+
private:
string * make_debug_string () final override;
void write_reproducer (reproducer &r) final override;
@@ -798,6 +867,13 @@ public:
: decorated_type (other_type),
m_num_units (num_units) {}
+ type* copy(context* ctxt) final override
+ {
+ type* result = new vector_type(m_other_type->copy (ctxt), m_num_units);
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_num_units () const { return m_num_units; }
vector_type *dyn_cast_vector_type () final override { return this; }
@@ -831,7 +907,7 @@ class array_type : public type
array_type (context *ctxt,
location *loc,
type *element_type,
- int num_elements)
+ unsigned long num_elements)
: type (ctxt),
m_loc (loc),
m_element_type (element_type),
@@ -840,12 +916,19 @@ class array_type : public type
type *dereference () final override;
+ type* copy(context* ctxt) final override
+ {
+ type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt), m_num_elements);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
type *is_pointer () final override { return NULL; }
type *is_array () final override { return m_element_type; }
- int num_elements () { return m_num_elements; }
+ unsigned long num_elements () { return m_num_elements; }
bool is_signed () const final override { return false; }
void replay_into (replayer *) final override;
@@ -857,7 +940,7 @@ class array_type : public type
private:
location *m_loc;
type *m_element_type;
- int m_num_elements;
+ unsigned long m_num_elements;
};
class function_type : public type
@@ -867,7 +950,8 @@ public:
type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *dereference () final override;
function_type *dyn_cast_function_type () final override { return this; }
@@ -875,6 +959,18 @@ public:
bool is_same_type_as (type *other) final override;
+ type* copy(context* ctxt) final override
+ {
+ auto_vec<type *> new_params{};
+ for (size_t i = 0; i < m_param_types.length (); i++)
+ new_params.safe_push (m_param_types[i]->copy (ctxt));
+
+ type* result = new function_type (ctxt, m_return_type->copy (ctxt), m_param_types.length (), new_params.address (),
+ m_is_variadic, m_is_target_builtin);
+ ctxt->record (result);
+ return result;
+ }
+
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 +983,7 @@ public:
type * get_return_type () const { return m_return_type; }
const vec<type *> &get_param_types () const { return m_param_types; }
int is_variadic () const { return m_is_variadic; }
+ int is_target_builtin () const { return m_is_target_builtin; }
string * make_debug_string_with_ptr ();
@@ -903,6 +1000,7 @@ private:
type *m_return_type;
auto_vec<type *> m_param_types;
int m_is_variadic;
+ int m_is_target_builtin;
};
class field : public memento
@@ -1004,9 +1102,11 @@ public:
return static_cast <playback::compound_type *> (m_playback_obj);
}
-private:
+protected:
location *m_loc;
string *m_name;
+
+private:
fields *m_fields;
};
@@ -1019,6 +1119,13 @@ public:
struct_ *dyn_cast_struct () final override { return this; }
+ type* copy(context* ctxt) final override
+ {
+ type* result = new struct_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
type *
as_type () { return this; }
@@ -1066,6 +1173,13 @@ public:
void replay_into (replayer *r) final override;
+ type* copy(context* ctxt) final override
+ {
+ type* result = new union_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_union () const final override { return true; }
private:
@@ -1188,7 +1302,8 @@ public:
m_link_section (NULL),
m_reg_name (NULL),
m_tls_model (GCC_JIT_TLS_MODEL_NONE),
- m_alignment (0)
+ m_alignment (0),
+ m_attributes ()
{}
playback::lvalue *
@@ -1208,6 +1323,14 @@ public:
as_rvalue () { return this; }
const char *access_as_rvalue (reproducer &r) override;
+
+ void set_readonly ()
+ {
+ m_readonly = true;
+ }
+
+ void add_attribute (gcc_jit_variable_attribute attribute, const char* value);
+
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 +1344,8 @@ protected:
string *m_reg_name;
enum gcc_jit_tls_model m_tls_model;
unsigned m_alignment;
+ bool m_readonly = false;
+ std::vector<std::pair<gcc_jit_variable_attribute, std::string>> m_attributes;
};
class param : public lvalue
@@ -1274,7 +1399,8 @@ public:
int num_params,
param **params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ int is_target_builtin);
void replay_into (replayer *r) final override;
@@ -1308,11 +1434,17 @@ public:
void write_to_dump (dump &d) final override;
+ bool is_target_builtin () const { return m_is_target_builtin; }
+
void validate ();
void dump_to_dot (const char *path);
rvalue *get_address (location *loc);
+ void set_personality_function (function *function);
+
+ void add_attribute (gcc_jit_fn_attribute attribute);
+ void add_string_attribute (gcc_jit_fn_attribute attribute, const char* value);
private:
string * make_debug_string () final override;
@@ -1329,6 +1461,9 @@ private:
auto_vec<local *> m_locals;
auto_vec<block *> m_blocks;
type *m_fn_ptr_type;
+ std::vector<gcc_jit_fn_attribute> m_attributes;
+ std::vector<std::pair<gcc_jit_fn_attribute, std::string>> m_string_attributes;
+ int m_is_target_builtin;
};
class block : public memento
@@ -1357,6 +1492,12 @@ public:
add_eval (location *loc,
rvalue *rvalue);
+ statement *
+ add_try_catch (location *loc,
+ block *try_block,
+ block *catch_block,
+ bool is_finally = false);
+
statement *
add_assignment (location *loc,
lvalue *lvalue,
@@ -1572,6 +1713,27 @@ private:
string *m_value;
};
+class memento_of_set_personality_function : public memento
+{
+public:
+ memento_of_set_personality_function (context *ctx,
+ function *func,
+ function *personality_function)
+ : memento(ctx),
+ m_function (func),
+ m_personality_function (personality_function) {}
+
+ void replay_into (replayer *r) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+
+private:
+ function *m_function;
+ function *m_personality_function;
+};
+
class memento_of_new_rvalue_from_vector : public rvalue
{
public:
@@ -1597,6 +1759,33 @@ private:
auto_vec<rvalue *> m_elements;
};
+class memento_of_new_rvalue_vector_perm : public rvalue
+{
+public:
+ memento_of_new_rvalue_vector_perm (context *ctxt,
+ location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask);
+
+ void replay_into (replayer *r) final override;
+
+ void visit_children (rvalue_visitor *) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+ enum precedence get_precedence () const final override
+ {
+ return PRECEDENCE_PRIMARY;
+ }
+
+private:
+ rvalue *m_elements1;
+ rvalue *m_elements2;
+ rvalue *m_mask;
+};
+
class ctor : public rvalue
{
public:
@@ -1879,6 +2068,64 @@ private:
rvalue *m_index;
};
+class convert_vector : public rvalue
+{
+public:
+ convert_vector (context *ctxt,
+ location *loc,
+ rvalue *vector,
+ type *type)
+ : rvalue (ctxt, loc, type),
+ m_vector (vector),
+ m_type (type)
+ {}
+
+ void replay_into (replayer *r) final override;
+
+ void visit_children (rvalue_visitor *v) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+ enum precedence get_precedence () const final override
+ {
+ return PRECEDENCE_POSTFIX;
+ }
+
+private:
+ rvalue *m_vector;
+ type *m_type;
+};
+
+class vector_access : public lvalue
+{
+public:
+ vector_access (context *ctxt,
+ location *loc,
+ rvalue *vector,
+ rvalue *index)
+ : lvalue (ctxt, loc, vector->get_type ()->dyn_cast_vector_type ()->get_element_type ()),
+ m_vector (vector),
+ m_index (index)
+ {}
+
+ void replay_into (replayer *r) final override;
+
+ void visit_children (rvalue_visitor *v) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+ enum precedence get_precedence () const final override
+ {
+ return PRECEDENCE_POSTFIX;
+ }
+
+private:
+ rvalue *m_vector;
+ rvalue *m_index;
+};
+
class access_field_of_lvalue : public lvalue
{
public:
@@ -2119,6 +2366,31 @@ private:
rvalue *m_rvalue;
};
+class try_catch : public statement
+{
+public:
+ try_catch (block *b,
+ location *loc,
+ block *try_block,
+ block *catch_block,
+ bool is_finally = false)
+ : statement (b, loc),
+ m_try_block (try_block),
+ m_catch_block (catch_block),
+ m_is_finally (is_finally) {}
+
+ void replay_into (replayer *r) final override;
+
+private:
+ string * make_debug_string () final override;
+ void write_reproducer (reproducer &r) final override;
+
+private:
+ block *m_try_block;
+ block *m_catch_block;
+ bool m_is_finally;
+};
+
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
+ <http://www.gnu.org/licenses/>. */
+
+#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
+<http://www.gnu.org/licenses/>. */
+
+#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 <algorithm>
+
+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<void *> ((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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#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 <unordered_map>
+#include <unordered_set>
+
+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<const char *, std::unordered_set<const char *, CStringHash, CStringEqual>, 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..050e68b738c 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -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 ();
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_const method, in
+ jit-recording.cc. */
+
+gcc_jit_type *
+gcc_jit_type_is_const (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->is_const ();
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -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,
- int num_elements)
+ unsigned long num_elements)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
@@ -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");
- RETURN_NULL_IF_FAIL_PRINTF2 (
+ // TODO: check at playback if the size is known.
+ /*RETURN_NULL_IF_FAIL_PRINTF2 (
type->has_known_size (),
ctxt, loc,
"unknown size for field \"%s\" (type: %s)",
name,
- type->get_debug_string ());
+ type->get_debug_string ());*/
RETURN_NULL_IF_FAIL_PRINTF1 (
!type->is_void (),
ctxt, loc,
@@ -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");
+ RETURN_VAL_IF_FAIL (struct_type->get_fields (), 0, NULL, NULL, "NULL fields");
return struct_type->get_fields ()->length ();
}
@@ -1745,6 +1766,23 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
reinterpret_cast<gcc::jit::recording::rvalue**>(values));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::get_target_builtin_function method, in
+ jit-recording.c. */
+
+gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name");
+
+ return static_cast <gcc_jit_function *> (ctxt->get_target_builtin_function (name));
+}
+
/* Public entrypoint. See description in libgccjit.h. */
extern gcc_jit_lvalue *
@@ -1853,6 +1891,23 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
return global;
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::global::set_readonly method, in
+ jit-recording.cc. */
+
+extern void
+gcc_jit_global_set_readonly (gcc_jit_lvalue *global)
+{
+ RETURN_IF_FAIL (global, NULL, NULL, "NULL global");
+ RETURN_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL,
+ "lvalue \"%s\" not a global",
+ global->get_debug_string ());
+
+ global->set_readonly ();
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this calls the trivial
@@ -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");
+ gcc::jit::recording::vector_type *vector_type = type->dyn_cast_vector_type ();
+ RETURN_NULL_IF_FAIL (vector_type == NULL, ctxt, loc, "cannot cast vector types");
RETURN_NULL_IF_FAIL_PRINTF3 (
is_valid_cast (rvalue->get_type (), type),
ctxt, loc,
@@ -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);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_convert_vector method in
+ jit-recording.cc. */
+
+gcc_jit_rvalue *
+gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (vector, ctxt, loc, "NULL vector");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+
+ // TODO: check if the value is a vector.
+ // TODO: check if type is a vector type.
+ // TODO: check if the number of elements in vector and type matches.
+
+ return (gcc_jit_rvalue *)ctxt->new_convert_vector (loc, vector, type);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_vector_access method in
+ jit-recording.cc. */
+
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_rvalue *index)
+{
+ RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index");
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ vector->get_type ()->dyn_cast_vector_type (),
+ ctxt, loc,
+ "vector: %s (type: %s) is not a vector",
+ vector->get_debug_string (),
+ vector->get_type ()->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ index->get_type ()->is_numeric (),
+ ctxt, loc,
+ "index: %s (type: %s) is not of numeric type",
+ index->get_debug_string (),
+ index->get_type ()->get_debug_string ());
+
+ return (gcc_jit_lvalue *)ctxt->new_vector_access (loc, vector, index);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -2801,6 +2912,64 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
rvalue->verify_valid_within_stmt (__func__, stmt);
}
+/* Public entrypoint. See description in libgccjit.h.
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::add_try_catch method in jit-recording.c. */
+
+void
+gcc_jit_block_add_try_catch (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *catch_block)
+{
+ RETURN_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
+ RETURN_IF_FAIL (catch_block, ctxt, loc, "NULL rvalue");
+
+ gcc::jit::recording::statement *stmt = block->add_try_catch (loc, try_block, catch_block);
+
+ // TODO: remove this or use it.
+ /* "stmt" should be good enough to be usable in error-messages,
+ but might still not be compilable; perform some more
+ error-checking here. We do this here so that the error messages
+ can contain a stringified version of "stmt", whilst appearing
+ as close as possible to the point of failure. */
+ /*try_block->verify_valid_within_stmt (__func__, stmt);
+ catch_block->verify_valid_within_stmt (__func__, stmt);*/
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::add_try_catch method in jit-recording.c. */
+
+void
+gcc_jit_block_add_try_finally (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *finally_block)
+{
+ RETURN_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
+ RETURN_IF_FAIL (finally_block, ctxt, loc, "NULL rvalue");
+
+ gcc::jit::recording::statement *stmt = block->add_try_catch (loc, try_block, finally_block, true);
+
+ // TODO: remove this or use it.
+ /* "stmt" should be good enough to be usable in error-messages,
+ but might still not be compilable; perform some more
+ error-checking here. We do this here so that the error messages
+ can contain a stringified version of "stmt", whilst appearing
+ as close as possible to the point of failure. */
+ /*try_block->verify_valid_within_stmt (__func__, stmt);
+ catch_block->verify_valid_within_stmt (__func__, stmt);*/
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -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 (),
- rvalue->get_type ()),
+ rvalue->get_type ()) || lvalue->get_type ()->is_const () != NULL,
ctxt, loc,
"mismatching types:"
" assignment to %s (type: %s) from %s (type: %s)",
@@ -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 (),
- rvalue->get_type ()),
+ rvalue->get_type ()) || lvalue->get_type ()->is_const () != NULL,
ctxt, loc,
"mismatching types:"
" assignment to %s (type: %s) involving %s (type: %s)",
@@ -3575,6 +3744,27 @@ gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
ctxt->add_command_line_option (optname);
}
+/* Public entrypoint. See description in libgccjit.h.
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function::set_personality_function method, in
+ jit-recording.c. */
+
+void
+gcc_jit_function_set_personality_function (gcc_jit_function *fn,
+ gcc_jit_function *personality_func)
+{
+ RETURN_IF_FAIL (fn, NULL, NULL, "NULL function");
+
+ fn->set_personality_function (personality_func);
+}
+
+extern char* jit_personality_func_name;
+
+void
+gcc_jit_set_global_personality_function_name (char* name) {
+ jit_personality_func_name = name;
+}
+
/* Public entrypoint. See description in libgccjit.h.
The real work is done by the
@@ -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);
}
+void
+gcc_jit_type_set_packed (gcc_jit_type *type)
+{
+ RETURN_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ type->set_packed ();
+}
+
+void
+gcc_jit_function_add_attribute (gcc_jit_function *func, gcc_jit_fn_attribute attribute)
+{
+ RETURN_IF_FAIL (func, NULL, NULL, "NULL func");
+
+ func->add_attribute (attribute);
+}
+
+void
+gcc_jit_function_add_string_attribute (gcc_jit_function *func, gcc_jit_fn_attribute attribute, const char* value)
+{
+ RETURN_IF_FAIL (func, NULL, NULL, "NULL func");
+
+ func->add_string_attribute (attribute, value);
+}
+
+void
+gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable, gcc_jit_variable_attribute attribute, const char* value)
+{
+ RETURN_IF_FAIL (variable, NULL, NULL, "NULL variable");
+
+ variable->add_attribute (attribute, value);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -4056,6 +4316,74 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
(gcc::jit::recording::rvalue **)elements);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_rvalue_vector_perm method, in
+ jit-recording.cc. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *elements1,
+ gcc_jit_rvalue *elements2,
+ gcc_jit_rvalue *mask)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+
+ /* LOC can be NULL. */
+
+ gcc::jit::recording::type *elements1_type = elements1->get_type ();
+ gcc::jit::recording::type *elements2_type = elements2->get_type ();
+ RETURN_NULL_IF_FAIL_PRINTF4 (
+ compatible_types (elements1->get_type ()->unqualified (),
+ elements2->get_type ()->unqualified ()),
+ ctxt, loc,
+ "mismatching types for vector perm:"
+ " elements1: %s (type: %s) elements2: %s (type: %s)",
+ elements1->get_debug_string (),
+ elements1_type->get_debug_string (),
+ elements2->get_debug_string (),
+ elements2_type->get_debug_string ());
+
+ gcc::jit::recording::type *mask_type = mask->get_type ();
+ gcc::jit::recording::vector_type *mask_vector_type = mask_type->dyn_cast_vector_type ();
+ gcc::jit::recording::vector_type *elements1_vector_type = elements1_type->dyn_cast_vector_type ();
+
+ size_t mask_len = mask_vector_type->get_num_units ();
+ size_t elements1_len = elements1_vector_type->get_num_units ();
+
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ mask_len == elements1_len,
+ ctxt, loc,
+ "mismatching length for mask:"
+ " elements1 length: %ld mask length: %ld",
+ mask_len,
+ elements1_len);
+
+ gcc::jit::recording::type *mask_element_type = mask_vector_type->get_element_type ();
+
+ RETURN_NULL_IF_FAIL (
+ mask_element_type->is_int (),
+ ctxt, loc,
+ "elements of mask must be of an integer type");
+
+ gcc::jit::recording::type *elements1_element_type = elements1_vector_type->get_element_type ();
+ size_t mask_element_size = mask_element_type->get_size ();
+ size_t elements1_element_size = elements1_element_type->get_size ();
+
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ mask_element_size == elements1_element_size,
+ ctxt, loc,
+ "mismatching size for mask element type:"
+ " elements1 element type: %ld mask element type: %ld",
+ mask_element_size,
+ elements1_element_size);
+
+ return (gcc_jit_rvalue *)ctxt->new_rvalue_vector_perm(loc, elements1, elements2, mask);
+}
+
/* A mutex around the cached state in parse_basever.
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..9663be4a069 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -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,
- GCC_JIT_TYPE_INT128_T
+ GCC_JIT_TYPE_INT128_T,
+
+ GCC_JIT_TYPE_BFLOAT16,
};
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,
- int num_elements);
+ unsigned long num_elements);
/* Struct-handling. */
@@ -1021,6 +1026,12 @@ extern gcc_jit_lvalue *
gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
gcc_jit_rvalue *init_value);
+/* Create a reference to a machine-specific builtin function (sometimes called
+ intrinsic functions). */
+extern gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name);
+
#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
/* Set an initial value for a global, which must be an array of
@@ -1036,6 +1047,9 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
const void *blob,
size_t num_bytes);
+extern void
+gcc_jit_global_set_readonly (gcc_jit_lvalue *global);
+
/* Upcasting. */
extern gcc_jit_object *
gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
@@ -1292,6 +1306,18 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index);
+extern gcc_jit_rvalue *
+gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_type *type);
+
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_rvalue *index);
+
/* Field access is provided separately for both lvalues and rvalues. */
/* Accessing a field of an lvalue of struct type, analogous to:
@@ -1391,6 +1417,38 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
gcc_jit_location *loc,
gcc_jit_rvalue *rvalue);
+/* Add a try/catch statement.
+ This is equivalent to this C++ code:
+ try {
+ try_block
+ }
+ catch (...) {
+ catch_block
+ }
+*/
+
+void
+gcc_jit_block_add_try_catch (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *catch_block);
+
+/* Add a try/finally statement.
+ This is equivalent to this C++-like code:
+ try {
+ try_block
+ }
+ finally {
+ finally_block
+ }
+*/
+
+void
+gcc_jit_block_add_try_finally (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_block *try_block,
+ gcc_jit_block *finally_block);
+
/* Add evaluation of an rvalue, assigning the result to the given
lvalue.
@@ -1788,6 +1846,12 @@ extern gcc_jit_rvalue *
gcc_jit_function_get_address (gcc_jit_function *fn,
gcc_jit_location *loc);
+void
+gcc_jit_function_set_personality_function (gcc_jit_function *fn,
+ gcc_jit_function *personality_func);
+
+extern void
+gcc_jit_set_global_personality_function_name (char* name);
#define LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
@@ -1806,6 +1870,21 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
size_t num_elements,
gcc_jit_rvalue **elements);
+/* Build a permutation vector rvalue from an 3 arrays of elements.
+
+ "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_25; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_TARGET_BUILTIN
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *elements1,
+ gcc_jit_rvalue *elements2,
+ gcc_jit_rvalue *mask);
+
#define LIBGCCJIT_HAVE_gcc_jit_version
/* Functions to retrieve libgccjit version.
@@ -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);
+/* Return the type behind const type or NULL if it's not a
+ * const type. */
+extern gcc_jit_type *
+gcc_jit_type_is_const (gcc_jit_type *type);
+
/* 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 +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);
+
+/* Function attributes. */
+enum gcc_jit_fn_attribute
+{
+ GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE,
+ GCC_JIT_FN_ATTRIBUTE_INLINE,
+ GCC_JIT_FN_ATTRIBUTE_NOINLINE,
+ 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. */
+// TODO: also support integer values.
+extern void
+gcc_jit_function_add_attribute (gcc_jit_function *func, enum gcc_jit_fn_attribute attribute);
+
+extern void
+gcc_jit_function_add_string_attribute (gcc_jit_function *func, enum gcc_jit_fn_attribute attribute, const char* value);
+
+/* Variable attributes. */
+enum gcc_jit_variable_attribute
+{
+ GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY,
+};
+
+/* Add an attribute to a variable. */
+// TODO: also support integer values.
+extern void
+gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable, enum gcc_jit_variable_attribute attribute, const char* value);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index cc22b2b414e..e52de0057a5 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -271,3 +271,58 @@ LIBGCCJIT_ABI_24 {
gcc_jit_lvalue_set_alignment;
gcc_jit_lvalue_get_alignment;
} LIBGCCJIT_ABI_23;
+
+LIBGCCJIT_ABI_25 {
+ global:
+ gcc_jit_type_set_packed;
+} LIBGCCJIT_ABI_24;
+
+LIBGCCJIT_ABI_26 {
+ global:
+ gcc_jit_type_is_const;
+} LIBGCCJIT_ABI_25;
+
+LIBGCCJIT_ABI_27 {
+ global:
+ gcc_jit_context_convert_vector;
+} LIBGCCJIT_ABI_26;
+
+LIBGCCJIT_ABI_28 {
+ global:
+ gcc_jit_global_set_readonly;
+} LIBGCCJIT_ABI_27;
+
+LIBGCCJIT_ABI_29 {
+ global:
+ gcc_jit_function_add_attribute;
+ gcc_jit_function_add_string_attribute;
+} LIBGCCJIT_ABI_28;
+
+LIBGCCJIT_ABI_30 {
+ global:
+ gcc_jit_lvalue_add_attribute;
+} LIBGCCJIT_ABI_29;
+
+LIBGCCJIT_ABI_31 {
+ global:
+ gcc_jit_block_add_try_catch;
+ gcc_jit_block_add_try_finally;
+ gcc_jit_function_set_personality_function;
+} LIBGCCJIT_ABI_30;
+
+LIBGCCJIT_ABI_32 {
+ global:
+ gcc_jit_context_get_target_builtin_function;
+ gcc_jit_context_new_rvalue_vector_perm;
+ 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
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -319,6 +319,9 @@
/* test-setting-alignment.c: This can't be in the testcases array as it
is target-specific. */
+/* test-target-builtins.c: This can't be in the testcases array as it
+ is target-specific. */
+
/* 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 <stdlib.h>
+#include <stdio.h>
+
+#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 <stdlib.h>
+#include <stdio.h>
+
+#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
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-target-builtins.c
@@ -0,0 +1,77 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#define TEST_PROVIDES_MAIN
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ CHECK_NON_NULL (gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_xgetbv"));
+ gcc_jit_function *builtin_eh_pointer = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_eh_pointer");
+ CHECK_NON_NULL (builtin_eh_pointer);
+
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *void_ptr =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);
+ gcc_jit_function *func_main =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "main",
+ 0, NULL,
+ 0);
+ gcc_jit_rvalue *zero = gcc_jit_context_zero (ctxt, int_type);
+ gcc_jit_block *block = gcc_jit_function_new_block (func_main, NULL);
+ gcc_jit_lvalue *variable = gcc_jit_function_new_local(func_main, NULL, void_ptr, "variable");
+ gcc_jit_block_add_assignment (block, NULL, variable,
+ gcc_jit_context_new_call (ctxt, NULL, builtin_eh_pointer, 1, &zero));
+ gcc_jit_block_end_with_return (block, NULL, zero);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+}
+
+int
+main (int argc, char **argv)
+{
+ /* This is the same as the main provided by harness.h, but it first create a dummy context and compile
+ in order to add the target builtins to libgccjit's internal state. */
+ gcc_jit_context *ctxt;
+ ctxt = gcc_jit_context_acquire ();
+ if (!ctxt)
+ {
+ fail ("gcc_jit_context_acquire failed");
+ return -1;
+ }
+ gcc_jit_result *result;
+ result = gcc_jit_context_compile (ctxt);
+ gcc_jit_result_release (result);
+ gcc_jit_context_release (ctxt);
+
+ int i;
+
+ for (i = 1; i <= 5; i++)
+ {
+ snprintf (test, sizeof (test),
+ "%s iteration %d of %d",
+ extract_progname (argv[0]),
+ i, 5);
+
+ //printf ("ITERATION %d\n", i);
+ test_jit (argv[0], NULL);
+ //printf ("\n");
+ }
+
+ totals ();
+
+ return 0;
+}
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 42937f0ba00..4469e0f069d 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2332,6 +2332,7 @@ toplev::finalize (void)
cgraphunit_cc_finalize ();
symtab_thunks_cc_finalize ();
dwarf2out_cc_finalize ();
+ dwarf2asm_cc_finalize ();
gcse_cc_finalize ();
ipa_cp_cc_finalize ();
ira_costs_cc_finalize ();
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 78b64ee98b3..ea95e67bb79 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15006,6 +15006,7 @@ void
tree_cc_finalize (void)
{
clear_nonstandard_integer_type_cache ();
+ gcc_eh_personality_decl = NULL;
}
#if CHECKING_P
diff --git a/gcc/tree.h b/gcc/tree.h
index e730a2a3e56..99695c647fe 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -6479,6 +6479,7 @@ extern tree get_inner_reference (tree, poly_int64_pod *, poly_int64_pod *,
tree *, machine_mode *, int *, int *, int *);
extern tree build_personality_function (const char *);
+extern tree build_personality_function_with_name (const char *);
struct GTY(()) int_n_trees_t {
/* These parts are initialized at runtime */