Hi.
Thanks for the review, David!
I talked to Arthur and he's OK with having a file to include in both
gccrs and libgccjit.
I sent the patch to gccrs to move the code in a new file that we can
include in both frontends: https://github.com/Rust-GCC/gccrs/pull/3195
I also renamed gcc_jit_target_info_supports_128bit_int to
gcc_jit_target_info_supports_target_dependent_type because a subsequent
patch will allow to check if other types are supported like _Float16 and
_Float128.
Here's the patch for libgccjit updated to include this file.
Thanks.
Le 2024-06-26 à 17 h 55, David Malcolm a écrit :
On Sun, 2024-03-10 at 12:05 +0100, Iain Buclaw wrote:
Excerpts from David Malcolm's message of März 5, 2024 4:09 pm:
On Thu, 2023-11-09 at 19:33 -0500, Antoni Boucher wrote:
Hi.
See answers below.
On Thu, 2023-11-09 at 18:04 -0500, David Malcolm wrote:
On Thu, 2023-11-09 at 17:27 -0500, Antoni Boucher wrote:
Hi.
This patch adds support for getting the CPU features in
libgccjit
(bug
112466)
There's a TODO in the test:
I'm not sure how to test that gcc_jit_target_info_arch
returns
the
correct value since it is dependant on the CPU.
Any idea on how to improve this?
Also, I created a CStringHash to be able to have a
std::unordered_set<const char *>. Is there any built-in way
of
doing
this?
Thanks for the patch.
Some high-level questions:
Is this specifically about detecting capabilities of the host
that
libgccjit is currently running on? or how the target was
configured
when libgccjit was built?
I'm less sure about this part. I'll need to do more tests.
One of the benefits of libgccjit is that, in theory, we support
all
of
the targets that GCC already supports. Does this patch change
that,
or
is this more about giving client code the ability to determine
capabilities of the specific host being compiled for?
This should not change that. If it does, this is a bug.
I'm nervous about having per-target jit code. Presumably
there's a
reason that we can't reuse existing target logic here - can you
please
describe what the problem is. I see that the ChangeLog has:
* config/i386/i386-jit.cc: New file.
where i386-jit.cc has almost 200 lines of nontrivial code.
Where
did
this come from? Did you base it on existing code in our source
tree,
making modifications to fit the new internal API, or did you
write
it
from scratch? In either case, how onerous would this be for
other
targets?
This was mostly copied from the same code done for the Rust and D
frontends.
See this commit and the following:
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b1c06fd9723453dd2b2ec306684cb806dc2b4fbb
The equivalent to i386-jit.cc is there:
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=22e3557e2d52f129f2bbfdc98688b945dba28dc9
[CCing Iain and Arthur re those patches; for reference, the patch
being
discussed is attached to :
https://gcc.gnu.org/pipermail/jit/2024q1/001792.html ]
One of my concerns about this patch is that we seem to be gaining
code
that's per-(frontend x config) which seems to be copied and pasted
with
a search and replace, which could lead to an M*N explosion.
That's certainly the case with the configure/make rules. Itself I
think
is copied originally from the {cpu_type}-protos.h machinery.
It might be worth pointing out that the c-family of front-ends don't
have separate headers because their per-target macros are defined in
{cpu_type}.h directly - for better or worse.
Is there any real difference between the per-config code for the
different frontends, or should there be a general "enumerate all
features of the target" hook that's independent of the frontend?
(but
perhaps calls into it).
As far as I understand, the configure parts should all be identical
between tm_p, tm_d, tm_rust, ..., so would benefit from being
templated
to aid any other front-ends adding in their own per target hooks.
Am I right in thinking that (rustc with default LLVM backend) has
some
set of feature strings that both (rustc with rustc_codegen_gcc) and
gccrs are trying to emulate? If so, is it presumably a goal that
libgccjit gives identical results to gccrs? If so, would it be
crazy
for libgccjit to consume e.g. config/i386/i386-rust.cc ?
I don't know whether libgccjit can just pull in directly the
implementation of the rust target hooks here.
Sorry for the delay in responding.
I don't want to be in the business of maintaining a copy of the per-
target code for "jit", and I think it makes sense for libgccjit to
return identical information compared to gccrs.
So I think it would be ideal for jit to share code with rust for this,
rather than do a one-time copy-and-paste followed by a ongoing "keep
things updated" treadmill.
Presumably there would be Makefile.in issues given that e.g. Makefile
has i386-rust.o listed in:
# Target specific, Rust specific object file
RUST_TARGET_OBJS= i386-rust.o linux-rust.o
One approach might be to move e.g. the i386-rust.cc code into, say, a
i386-rust-and-jit.inc file and #include it from i386-rust.cc and i386-
jit.cc (with a similar approach for other targets)
Antoni, Arthur, would you each be OK with that?
The per-frontend target
hooks usually also make use of code specific to that front-end -
TARGET_CPU_CPP_BUILTINS and others can't be used by a non-c-family
front-end without adding a plethora of stubs, for example.
Whether or not libgccjit wants to give identical information as as
rust
I think is a decision for you as the maintainer of its API.
Also a question for Antoni and Arthur: is that desirable for the two
gcc rust approaches?
Thanks
Dave
From 033c79bfb45cdc6a3e6aac8ad4046c494cb2e48b Mon Sep 17 00:00:00 2001
From: Antoni Boucher <boua...@zoho.com>
Date: Wed, 16 Oct 2024 16:43:41 -0400
Subject: [PATCH] libgccjit: Add ability to get CPU features
gcc/ChangeLog:
PR jit/112466
* Makefile.in (tm_jit_file_list, tm_jit_include_list, TM_JIT_H,
JIT_TARGET_DEF, JIT_TARGET_H, JIT_TARGET_OBJS): New variables.
(tm_jit.h, cs-tm_jit.h, jit/jit-target-hooks-def.h,
s-jit-target-hooks-def-h, default-jit.o): New rules.
(s-tm-texi): Also check timestamp on jit-target.def.
(generated_files): Add TM_JIT_H and jit/jit-target-hooks-def.h.
(build/genhooks.o): Also depend on JIT_TARGET_DEF.
* config.gcc (tm_jit_file, jit_target_objs, target_has_targetjitm):
New variables.
* config/i386/t-i386 (i386-jit.o): New rule.
* config/t-linux (linux-jit.o): New rule.
* configure: Regenerate.
* configure.ac (tm_jit_file_list, tm_jit_include_list,
jit_target_objs): Add substitutes.
* doc/tm.texi: Regenerate.
* doc/tm.texi.in (targetjitm): Document.
(target_has_targetjitm): Document.
* genhooks.cc: Include jit/jit-target.def.
* config/default-jit.cc: New file.
* config/i386/i386-jit.cc: New file.
* config/i386/i386-jit.h: New file.
* config/linux-jit.cc: New file.
gcc/jit/ChangeLog:
PR jit/112466
* Make-lang.in (JIT_OBJS): New variable.
* jit-playback.cc (replay): Include jit-target.h and initialize
target.
* jit-playback.h (class get_target_info): New class.
* jit-recording.cc (recording::context::get_target_info): New
method.
* jit-recording.h (recording::context::get_target_info): New
method.
* libgccjit.cc: Include jit-target.h.
(struct gcc_jit_target_info): New struct.
(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_target_dependent_type): New functions.
* libgccjit.h (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_target_dependent_type):
New functions.
* libgccjit.map (LIBGCCJIT_ABI_26): New ABI tag.
* docs/topics/compilation.rst: Add documentation for the
functions 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_target_dependent_type.
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag.
* jit-target-def.h: New file.
* jit-target.cc: New file.
* jit-target.def: New file.
* jit-target.h: New file.
gcc/testsuite/ChangeLog:
PR jit/112466
* jit.dg/all-non-failing-tests.h: Mention
test-target-info.c.
* jit.dg/test-target-info.c: New test.
---
gcc/Makefile.in | 36 +++++++-
gcc/config.gcc | 54 ++++++++++++
gcc/config/default-jit.cc | 28 ++++++
gcc/config/i386/i386-jit.cc | 63 ++++++++++++++
gcc/config/i386/i386-jit.h | 22 +++++
gcc/config/i386/t-i386 | 4 +
gcc/config/linux-jit.cc | 37 ++++++++
gcc/config/t-linux | 4 +
gcc/configure | 14 +++
gcc/configure.ac | 14 +++
gcc/doc/tm.texi | 26 ++++++
gcc/doc/tm.texi.in | 16 ++++
gcc/genhooks.cc | 1 +
gcc/jit/Make-lang.in | 8 +-
gcc/jit/jit-playback.cc | 2 +
gcc/jit/jit-playback.h | 17 +++-
gcc/jit/jit-recording.cc | 19 +++++
gcc/jit/jit-recording.h | 3 +
gcc/jit/jit-target-def.h | 20 +++++
gcc/jit/jit-target.cc | 89 ++++++++++++++++++++
gcc/jit/jit-target.def | 52 ++++++++++++
gcc/jit/jit-target.h | 70 +++++++++++++++
gcc/jit/libgccjit.cc | 43 ++++++++++
gcc/jit/libgccjit.h | 22 +++++
gcc/jit/libgccjit.map | 9 ++
gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 +
gcc/testsuite/jit.dg/test-target-info.c | 63 ++++++++++++++
27 files changed, 732 insertions(+), 7 deletions(-)
create mode 100644 gcc/config/default-jit.cc
create mode 100644 gcc/config/i386/i386-jit.cc
create mode 100644 gcc/config/i386/i386-jit.h
create mode 100644 gcc/config/linux-jit.cc
create mode 100644 gcc/jit/jit-target-def.h
create mode 100644 gcc/jit/jit-target.cc
create mode 100644 gcc/jit/jit-target.def
create mode 100644 gcc/jit/jit-target.h
create mode 100644 gcc/testsuite/jit.dg/test-target-info.c
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 059cf2e8f79..ef7e7f70935 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -604,6 +604,8 @@ tm_d_file_list=@tm_d_file_list@
tm_d_include_list=@tm_d_include_list@
tm_rust_file_list=@tm_rust_file_list@
tm_rust_include_list=@tm_rust_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@
@@ -903,6 +905,7 @@ TCONFIG_H = tconfig.h $(xm_file_list)
TM_P_H = tm_p.h $(tm_p_file_list) $(TREE_H)
TM_D_H = tm_d.h $(tm_d_file_list)
TM_RUST_H = tm_rust.h $(tm_rust_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)
@@ -962,11 +965,13 @@ 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
RUST_TARGET_DEF = rust/rust-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)
RUST_TARGET_H = rust/rust-target.h $(RUST_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)
@@ -1280,6 +1285,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@
@@ -2042,6 +2050,7 @@ tm.h: cs-tm.h ; @true
tm_p.h: cs-tm_p.h ; @true
tm_d.h: cs-tm_d.h ; @true
tm_rust.h: cs-tm_rust.h ; @true
+tm_jit.h: cs-tm_jit.h ; @true
cs-config.h: Makefile
TARGET_CPU_DEFAULT="" \
@@ -2081,6 +2090,11 @@ cs-tm_rust.h: Makefile
HEADERS="$(tm_rust_include_list)" DEFINES="" \
$(SHELL) $(srcdir)/mkconfig.sh tm_rust.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
@@ -2417,6 +2431,12 @@ default-d.o: config/default-d.cc
$(COMPILE) $<
$(POSTCOMPILE)
+# Files used by the JIT language front end.
+
+default-jit.o: config/default-jit.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
# Files used by the Rust language front end.
default-rust.o: config/default-rust.cc
@@ -2756,6 +2776,15 @@ s-rust-target-hooks-def-h: build/genhooks$(build_exeext)
rust/rust-target-hooks-def.h
$(STAMP) s-rust-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
@@ -2950,7 +2979,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 \
@@ -2962,6 +2991,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
$(TM_RUST_H) rust/rust-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
#
@@ -3095,8 +3125,8 @@ 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) $(RUST_TARGET_DEF) $(BCONFIG_H) \
- $(SYSTEM_H) errors.h
+ $(COMMON_TARGET_DEF) $(D_TARGET_DEF) $(RUST_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) $(CORETYPES_H) \
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 71ac3badafd..91847df8217 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -149,6 +149,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.
#
@@ -210,6 +213,9 @@
#
# target_has_targetrustm Set to yes or no depending on whether the target
# has its own definition of targetrustm.
+#
+# target_has_targetjitm Set to yes or no depending on whether the target
+# has its own definition of targetdm.
out_file=
common_out_file=
@@ -226,12 +232,14 @@ extra_options=
c_target_objs=
cxx_target_objs=
d_target_objs=
+jit_target_objs=
fortran_target_objs=
rust_target_objs=
target_has_targetcm=no
target_has_targetm_common=yes
target_has_targetdm=no
target_has_targetrustm=no
+target_has_targetjitm=no
tm_defines=
xm_defines=
# Set this to force installation and use of collect2.
@@ -381,6 +389,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"
;;
@@ -416,6 +425,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"
@@ -485,6 +495,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"
@@ -574,11 +585,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"
target_gtfiles="./s390-gen-builtins.h"
@@ -625,6 +638,12 @@ then
rust_target_objs="${rust_target_objs} ${cpu_type}-rust.o"
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
@@ -792,11 +811,13 @@ 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"
rust_target_objs="${rust_target_objs} darwin-rust.o"
target_has_targetcm=yes
target_has_targetdm=yes
target_has_targetrustm=yes
+ #target_has_targetjitm=yes
extra_objs="${extra_objs} darwin.o"
extra_gcc_objs="darwin-driver.o"
default_use_cxa_atexit=yes
@@ -825,10 +846,12 @@ 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
rust_target_objs="${rust_target_objs} dragonfly-rust.o"
target_has_targetrustm=yes
+ #target_has_targetjitm=yes
;;
*-*-freebsd*)
# This is the generic ELF configuration of FreeBSD. Later
@@ -878,10 +901,12 @@ 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
rust_target_objs="${rust_target_objs} freebsd-rust.o"
target_has_targetrustm=yes
+ #target_has_targetjitm=yes
;;
*-*-fuchsia*)
native_system_header_dir=/include
@@ -957,21 +982,29 @@ 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
rust_target_objs="${rust_target_objs} linux-rust.o"
target_has_targetrustm=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
;;
@@ -980,6 +1013,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
@@ -989,6 +1023,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
@@ -1010,9 +1045,11 @@ 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
rust_target_objs="${rust_target_objs} openbsd-rust.o"
target_has_targetrustm=yes
+ #target_has_targetjitm=yes
;;
*-*-phoenix*)
gas=yes
@@ -1065,6 +1102,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
@@ -1075,6 +1113,7 @@ case ${target} in
target_has_targetdm=yes
rust_target_objs="${rust_target_objs} sol2-rust.o"
target_has_targetrustm=yes
+ #target_has_targetjitm=yes
;;
*-*-*vms*)
extra_options="${extra_options} vms/vms.opt"
@@ -1863,6 +1902,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*)
@@ -1871,6 +1911,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"
@@ -1879,6 +1920,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
;;
@@ -1916,6 +1958,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
@@ -2195,7 +2238,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
@@ -2216,7 +2261,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
@@ -2230,10 +2277,12 @@ 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"
rust_target_objs="${rust_target_objs} winnt-rust.o"
target_has_targetrustm="yes"
+ #target_has_targetjitm=yes
case ${target} in
x86_64-*-* | *-w64-*)
need_64bit_isa=yes
@@ -3721,6 +3770,10 @@ if [ "$target_has_targetrustm" = "no" ]; then
rust_target_objs="$rust_target_objs default-rust.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
@@ -6022,6 +6075,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..6c76c8e0728
--- /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_targetjitm targetjitm = TARGETJITM_INITIALIZER;
diff --git a/gcc/config/i386/i386-jit.cc b/gcc/config/i386/i386-jit.cc
new file mode 100644
index 00000000000..725f7075a39
--- /dev/null
+++ b/gcc/config/i386/i386-jit.cc
@@ -0,0 +1,63 @@
+/* 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_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* local_cpu = host_detect_local_cpu (2, params);
+ std::string arch = local_cpu;
+ free (const_cast <char *> (local_cpu));
+
+ const char* arg = "-march=";
+ size_t arg_pos = arch.find (arg) + strlen (arg);
+ size_t end_pos = arch.find (" ", arg_pos);
+
+ std::string cpu = arch.substr (arg_pos, end_pos - arg_pos);
+ jit_target_set_arch (cpu);
+
+ if (targetm.scalar_mode_supported_p (TImode))
+ {
+ jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_UINT128_T);
+ jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_INT128_T);
+ }
+
+#define ADD_TARGET_INFO jit_add_target_info
+#include "i386-rust-and-jit.inc"
+#undef ADD_TARGET_INFO
+}
diff --git a/gcc/config/i386/i386-jit.h b/gcc/config/i386/i386-jit.h
new file mode 100644
index 00000000000..4f05e88003f
--- /dev/null
+++ b/gcc/config/i386/i386-jit.h
@@ -0,0 +1,22 @@
+/* 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_register_target_info (void);
+
+/* Target hooks for jit language. */
+#define TARGET_JIT_REGISTER_CPU_TARGET_INFO ix86_jit_register_target_info
diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386
index bf4ae109af9..3452193c45f 100644
--- a/gcc/config/i386/t-i386
+++ b/gcc/config/i386/t-i386
@@ -50,6 +50,10 @@ i386-rust.o: $(srcdir)/config/i386/i386-rust.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..cf8d55b8c53
--- /dev/null
+++ b/gcc/config/linux-jit.cc
@@ -0,0 +1,37 @@
+/* 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_REGISTER_OS_TARGET_INFO for Linux targets. */
+
+static void
+linux_jit_register_target_info (void)
+{
+}
+
+#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 5c5bfc5ca83..dd705361068 100644
--- a/gcc/config/t-linux
+++ b/gcc/config/t-linux
@@ -27,3 +27,7 @@ linux-d.o: $(srcdir)/config/linux-d.cc
linux-rust.o: $(srcdir)/config/linux-rust.cc
$(COMPILE) $<
$(POSTCOMPILE)
+
+linux-jit.o: $(srcdir)/config/linux-jit.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/configure b/gcc/configure
index 5acc42c1e4d..9478be31dec 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -648,6 +648,7 @@ GMPLIBS
target_cpu_default
rust_target_objs
d_target_objs
+jit_target_objs
fortran_target_objs
cxx_target_objs
c_target_objs
@@ -659,6 +660,8 @@ tm_rust_include_list
tm_rust_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
@@ -15034,6 +15037,17 @@ for f in $tm_rust_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 23f4884eff9..131c3a23584 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2423,6 +2423,17 @@ for f in $tm_rust_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
@@ -7542,6 +7553,8 @@ AC_SUBST(tm_d_file_list)
AC_SUBST(tm_d_include_list)
AC_SUBST(tm_rust_file_list)
AC_SUBST(tm_rust_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)
@@ -7551,6 +7564,7 @@ AC_SUBST(cxx_target_objs)
AC_SUBST(fortran_target_objs)
AC_SUBST(d_target_objs)
AC_SUBST(rust_target_objs)
+AC_SUBST(jit_target_objs)
AC_SUBST(target_cpu_default)
AC_SUBST_FILE(language_hooks)
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4deb3d2c283..70acde767ec 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -124,6 +124,14 @@ If targets initialize @code{targetrustm} themselves, they should set
@code{target_has_targetrustm=yes} in @file{config.gcc}; otherwise a
default definition is used.
+Similarly, there is a @code{targetjitm} variable for hooks that are
+specific to the jit front end, documented as ``JIT Target Hook''.
+This is declared in @file{jit/jit-target.h}, the initializer
+@code{TARGETJITM_INITIALIZER} in @file{jit/jit-target-def.h}. If targets
+initialize @code{targetjitm} themselves, they should set
+@code{target_has_targetjitm=yes} in @file{config.gcc}; otherwise a default
+definition is used.
+
@node Driver
@section Controlling the Compilation Driver, @file{gcc}
@cindex driver
@@ -11260,6 +11268,24 @@ Similar to @code{TARGET_RUST_CPU_INFO}, but is used for configuration info
relating to the target operating system.
@end deftypefn
+@node JIT Language and ABI
+@section JIT ABI parameters
+@cindex parameters, jit abi
+
+@deftypefn {JIT Target Hook} void TARGET_JIT_REGISTER_CPU_TARGET_INFO (void)
+Register all target information keys relating to the target CPU using the
+function @code{jit_add_target_info_handlers}, which takes a
+@samp{struct jit_target_info_spec} (defined in @file{jit/jit-target.h}). The keys
+added by this hook are made available at compile time by the
+@code{__traits(getTargetInfo)} extension, the result is an expression
+describing the requested target information.
+@end deftypefn
+
+@deftypefn {JIT Target Hook} void TARGET_JIT_REGISTER_OS_TARGET_INFO (void)
+Same as @code{TARGET_JIT_CPU_TARGET_INFO}, but is used for keys relating to
+the target operating system.
+@end deftypefn
+
@node Named Address Spaces
@section Adding support for named address spaces
@cindex named address spaces
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 9f147ccb95c..5d24844799c 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -124,6 +124,14 @@ If targets initialize @code{targetrustm} themselves, they should set
@code{target_has_targetrustm=yes} in @file{config.gcc}; otherwise a
default definition is used.
+Similarly, there is a @code{targetjitm} variable for hooks that are
+specific to the jit front end, documented as ``JIT Target Hook''.
+This is declared in @file{jit/jit-target.h}, the initializer
+@code{TARGETJITM_INITIALIZER} in @file{jit/jit-target-def.h}. If targets
+initialize @code{targetjitm} themselves, they should set
+@code{target_has_targetjitm=yes} in @file{config.gcc}; otherwise a default
+definition is used.
+
@node Driver
@section Controlling the Compilation Driver, @file{gcc}
@cindex driver
@@ -7263,6 +7271,14 @@ floating-point support; they are not included in this mechanism.
@hook TARGET_RUST_OS_INFO
+@node JIT Language and ABI
+@section JIT ABI parameters
+@cindex parameters, jit abi
+
+@hook TARGET_JIT_REGISTER_CPU_TARGET_INFO
+
+@hook TARGET_JIT_REGISTER_OS_TARGET_INFO
+
@node Named Address Spaces
@section Adding support for named address spaces
@cindex named address spaces
diff --git a/gcc/genhooks.cc b/gcc/genhooks.cc
index 8a55ad184d6..b5898f471fa 100644
--- a/gcc/genhooks.cc
+++ b/gcc/genhooks.cc
@@ -36,6 +36,7 @@ static struct hook_desc hook_array[] = {
#include "common/common-target.def"
#include "d/d-target.def"
#include "rust/rust-target.def"
+#include "jit/jit-target.def"
#undef DEFHOOK
};
diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
index 99b3d549d5d..c2aa6bd8e28 100644
--- a/gcc/jit/Make-lang.in
+++ b/gcc/jit/Make-lang.in
@@ -130,7 +130,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 \
@@ -139,13 +139,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/jit-playback.cc b/gcc/jit/jit-playback.cc
index 583956fb463..3027217369b 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -47,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"
@@ -3400,6 +3401,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 6e97b389cbb..a840392c79e 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -54,9 +54,10 @@ set_variable_string_attribute (
/* 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
{
@@ -436,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.
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index cc7f529c9e8..fcf4661fcd0 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1556,6 +1556,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. */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index abd4f6f8bb3..ec296d7b630 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -298,6 +298,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);
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..2448d0d3da0
--- /dev/null
+++ b/gcc/jit/jit-target.cc
@@ -0,0 +1,89 @@
+/* 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 (std::string const& arch)
+{
+ jit_target_info.m_arch = arch;
+}
+
+void
+jit_target_add_supported_target_dependent_type(enum gcc_jit_types type_)
+{
+ jit_target_info.m_supported_target_dependent_types.insert(type_);
+}
+
+target_info *
+jit_get_target_info ()
+{
+ target_info *info = new target_info {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..3d60b01ac13
--- /dev/null
+++ b/gcc/jit/jit-target.def
@@ -0,0 +1,52 @@
+/* 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_"
+
+/* 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..061a5018395
--- /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 "libgccjit.h"
+
+#include <string>
+#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:
+ 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;
+ std::string m_arch;
+ std::unordered_set<enum gcc_jit_types> m_supported_target_dependent_types;
+};
+
+/* Each target can provide their own. */
+extern struct gcc_targetjitm targetjitm;
+
+extern void jit_target_init ();
+extern void jit_target_set_arch (std::string const& arch);
+extern void jit_target_add_supported_target_dependent_type(enum gcc_jit_types type_);
+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 eb38da91df1..0de82ce1019 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
{
};
@@ -3715,6 +3720,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.c_str ();
+}
+
+int
+gcc_jit_target_info_supports_target_dependent_type(gcc_jit_target_info *info, enum gcc_jit_types type)
+{
+ return info->m_supported_target_dependent_types.find(type) != info->m_supported_target_dependent_types.end();
+}
/* Public entrypoint. See description in libgccjit.h.
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 03bfc0f58a5..48614010cc7 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -57,6 +57,12 @@ 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;
+
+/* 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.
@@ -2064,6 +2070,22 @@ gcc_jit_function_add_string_attribute (gcc_jit_function *func,
enum gcc_jit_fn_attribute attribute,
const char* value);
+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_target_dependent_type(gcc_jit_target_info *info, enum gcc_jit_types type);
+
extern void
gcc_jit_function_add_integer_array_attribute (
gcc_jit_function *func,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index b02783ebfb2..988cfbf6fdd 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -294,3 +294,12 @@ LIBGCCJIT_ABI_28 {
global:
gcc_jit_context_new_alignof;
} LIBGCCJIT_ABI_27;
+
+LIBGCCJIT_ABI_29 {
+ 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_target_dependent_type;
+} LIBGCCJIT_ABI_28;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 75721329ab5..c75e9a532eb 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -391,6 +391,9 @@
#undef create_code
#undef verify_code
+/* test-target-info.c: This can't be in the testcases array as it
+ is target-specific. */
+
/* test-types.c */
#define create_code create_code_types
#define verify_code verify_code_types
diff --git a/gcc/testsuite/jit.dg/test-target-info.c b/gcc/testsuite/jit.dg/test-target-info.c
new file mode 100644
index 00000000000..db5591edcbd
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-target-info.c
@@ -0,0 +1,63 @@
+/* { 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)
+{
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ /* This is the same as the main provided by harness.h, but calls gcc_jit_context_get_target_info. */
+ gcc_jit_context *ctxt;
+ ctxt = gcc_jit_context_acquire ();
+ if (!ctxt)
+ {
+ fail ("gcc_jit_context_acquire failed");
+ return -1;
+ }
+ gcc_jit_target_info* info = gcc_jit_context_get_target_info (ctxt);
+
+ int sse2_supported = gcc_jit_target_info_cpu_supports (info, "sse2");
+ CHECK_VALUE (sse2_supported, 1);
+
+ const char *arch = gcc_jit_target_info_arch (info);
+ // TODO: not sure what value to check here.
+ CHECK_STRING_VALUE (arch, "znver2");
+
+ int supports_128bit_int = gcc_jit_target_info_supports_128bit_int (info);
+ CHECK_VALUE (supports_128bit_int, 1);
+ gcc_jit_target_info_release (info);
+ 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;
+}
--
2.47.0