diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000000..058eb16400029 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,86 @@ +name: CI + +permissions: + contents: write + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-24.04 + + strategy: + fail-fast: false + matrix: + version: + - { use_patch: true, asset_name: "gcc-15-without-int128.deb" } + - { use_path: false, asset_name: "gcc-15.deb" } + + steps: + - uses: actions/checkout@v2 + + - name: Install mpfr + run: sudo apt-get install gcc-10 libmpfr-dev libmpc-dev + + - name: Apply patch to disable 128-bit integers + if: matrix.version.use_patch + run: git apply patches/0001-Disable-128-bit-integers-for-testing-purposes.patch + + - name: Build libgccjit + run: | + cd .. + ls + mkdir build install + cd build + ../gcc/configure --enable-host-shared --enable-languages=c,jit,lto --disable-bootstrap --disable-multilib --prefix=$(pwd)/../install/usr --libdir=$(pwd)/../install/usr/lib --libexecdir=$(pwd)/../install/usr/lib + make -j4 + make install + + - name: Build Debian package + run: | + cd .. + mkdir install/DEBIAN + cat > install/DEBIAN/control << EOF + Package: gcc-15 + Version: 15 + Architecture: amd64 + Maintainer: Antoni Boucher + Description: gcc 15 for rustc_codegen_gcc CI + EOF + dpkg-deb --root-owner-group --build install + mv install.deb gcc-15.deb + + - name: Compute tag name + id: tag_name + run: | + git_hash=$(git rev-parse "$GITHUB_SHA") + echo "TAG_NAME=$git_hash" >> $GITHUB_OUTPUT + + - name: Create tag + if: github.ref == 'refs/heads/master' + continue-on-error: true + uses: laputansoft/github-tag-action@v4.6 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + create_annotated_tag: true + tag: master-${{ steps.tag_name.outputs.TAG_NAME }} + + - name: Create release + if: github.ref == 'refs/heads/master' && !matrix.version.use_patch + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: /home/runner/work/gcc/install/usr/lib/libgccjit.so.0.0.1 + asset_name: libgccjit.so + tag: master-${{ steps.tag_name.outputs.TAG_NAME }} + + - name: Create release + if: github.ref == 'refs/heads/master' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: /home/runner/work/gcc/gcc-15.deb + asset_name: ${{ matrix.version.asset_name }} + tag: master-${{ steps.tag_name.outputs.TAG_NAME }} diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites index b83fcc9db5dde..ce7efe1d1edc9 100755 --- a/contrib/download_prerequisites +++ b/contrib/download_prerequisites @@ -33,7 +33,11 @@ mpc='mpc-1.2.1.tar.gz' isl='isl-0.24.tar.bz2' gettext='gettext-0.22.tar.gz' -base_url='http://gcc.gnu.org/pub/gcc/infrastructure/' +#base_url='http://gcc.gnu.org/pub/gcc/infrastructure/' +# We use rust-lang mirrors because the GCC infrastructure is unreliable. +# When dependencies are changed, we have to modify our mirrors. +# Please contact t-infra for that. +base_url='https://ci-mirrors.rust-lang.org/rustc/gcc/' echo_archives() { echo "${gettext}" diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ebfcd8a8a0d33..47d662c0835fc 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -615,6 +615,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@ @@ -919,6 +921,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) @@ -978,11 +981,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) @@ -1297,6 +1302,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@ @@ -2081,6 +2089,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="" \ @@ -2120,6 +2129,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 @@ -2587,6 +2601,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 @@ -2939,6 +2959,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 @@ -3135,7 +3164,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 \ @@ -3147,6 +3176,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 # @@ -3280,8 +3310,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/analyzer/checker-event.h b/gcc/analyzer/checker-event.h index f92f514fc028c..087868a8c5eba 100644 --- a/gcc/analyzer/checker-event.h +++ b/gcc/analyzer/checker-event.h @@ -565,6 +565,8 @@ class inlined_call_event : public checker_event m_apparent_callee_fndecl (apparent_callee_fndecl), m_apparent_caller_fndecl (apparent_caller_fndecl) { + gcc_assert (apparent_callee_fndecl != NULL); + gcc_assert (apparent_caller_fndecl != NULL); gcc_assert (LOCATION_BLOCK (loc) == NULL); } diff --git a/gcc/config.gcc b/gcc/config.gcc index f7f2002a45f33..9a9079d941d8d 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. @@ -350,6 +358,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 aarch64-sve-builtins-sme.o cortex-a57-fma-steering.o aarch64-speculation.o aarch-bti-insert.o aarch64-cc-fusion.o aarch64-early-ra.o aarch64-ldp-fusion.o" target_gtfiles="\$(srcdir)/config/aarch64/aarch64-protos.h \$(srcdir)/config/aarch64/aarch64-builtins.h \$(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 @@ -380,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" ;; @@ -415,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 +496,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" @@ -570,11 +582,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" @@ -621,6 +635,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 @@ -788,11 +808,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 @@ -821,10 +843,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 @@ -874,10 +898,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 @@ -953,21 +979,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 ;; @@ -976,6 +1010,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 @@ -985,6 +1020,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 @@ -1006,9 +1042,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 @@ -1061,6 +1099,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 @@ -1071,6 +1110,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" @@ -1861,6 +1901,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*) @@ -1869,6 +1910,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" @@ -1877,6 +1919,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 ;; @@ -1914,6 +1957,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 @@ -2193,7 +2237,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 @@ -2214,7 +2260,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 @@ -2228,10 +2276,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 @@ -3702,6 +3752,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 @@ -6058,6 +6112,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/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index 93f939a9c834c..7211cc47edfea 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -1262,6 +1262,8 @@ aarch64_init_simd_builtin_types (void) if (aarch64_simd_types_trees[i].itype == NULL) { + // FIXME: problem happens when we execute this a second time. + // Currently fixed by not initializing builtins more than once in dummy-frontend.cc. tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode)); type = build_distinct_type_copy (type); SET_TYPE_STRUCTURAL_EQUALITY (type); diff --git a/gcc/config/aarch64/aarch64-jit.cc b/gcc/config/aarch64/aarch64-jit.cc new file mode 100644 index 0000000000000..8c6b130464ca2 --- /dev/null +++ b/gcc/config/aarch64/aarch64-jit.cc @@ -0,0 +1,142 @@ +/* Subroutines for the jit front end on the AArch64 architecture. + Copyright (C) 2024 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tm_jit.h" +#include +#include "jit/jit-target.h" +#include "jit/jit-target-def.h" + +/* Implement TARGET_JIT_REGISTER_CPU_TARGET_INFO. */ + +void +aarch64_jit_register_target_info (void) +{ +#define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) +#define extractBits(val, start, number) \ + (val & ((1ULL << number) - 1ULL) << start) >> start + + const char *params[] = {"arch"}; + const char* local_cpu = host_detect_local_cpu (2, params); + std::string arch = local_cpu; + free (const_cast (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 (TARGET_AES) + jit_add_target_info ("target_feature", "aes"); + if (TARGET_BF16_FP) + jit_add_target_info ("target_feature", "bf16"); + if (TARGET_BTI) + jit_add_target_info ("target_feature", "bti"); + if (TARGET_COMPLEX) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "fcma"); + if (TARGET_CRC32) + jit_add_target_info ("target_feature", "crc"); + if (TARGET_DOTPROD) + jit_add_target_info ("target_feature", "dotprod"); + if (TARGET_SVE_F32MM) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "f32mm"); + if (TARGET_SVE_F64MM) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "f64mm"); + if (TARGET_F16FML) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "fhm"); + if (TARGET_FP_F16INST) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "fp16"); + if (TARGET_FRINT) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "frintts"); + if (TARGET_I8MM) + jit_add_target_info ("target_feature", "i8mm"); + if (TARGET_JSCVT) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "jsconv"); + if (TARGET_LSE) + jit_add_target_info ("target_feature", "lse"); + if (TARGET_MEMTAG) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "mte"); + if (TARGET_PAUTH) + { + jit_add_target_info ("target_feature", "paca"); + jit_add_target_info ("target_feature", "pacg"); + } + if (TARGET_RNG) + jit_add_target_info ("target_feature", "rand"); + if (TARGET_RCPC) + jit_add_target_info ("target_feature", "rcpc"); + if (TARGET_RCPC2) + jit_add_target_info ("target_feature", "rcpc2"); + if (TARGET_SIMD_RDMA) + // TODO: check if this is the correct match. + jit_add_target_info ("target_feature", "rdm"); + if (TARGET_SB) + jit_add_target_info ("target_feature", "sb"); + if (TARGET_SHA2) + jit_add_target_info ("target_feature", "sha2"); + if (TARGET_SHA3) + jit_add_target_info ("target_feature", "sha3"); + if (TARGET_SIMD) + jit_add_target_info ("target_feature", "neon"); + if (TARGET_SM4) + jit_add_target_info ("target_feature", "sm4"); + if (TARGET_SVE) + jit_add_target_info ("target_feature", "sve"); + if (TARGET_SVE2) + jit_add_target_info ("target_feature", "sve2"); + if (TARGET_SVE2_AES) + jit_add_target_info ("target_feature", "sve2-aes"); + if (TARGET_SVE2_BITPERM) + jit_add_target_info ("target_feature", "sve2-bitperm"); + if (TARGET_SVE2_SHA3) + jit_add_target_info ("target_feature", "sve2-sha3"); + if (TARGET_SVE2_SM4) + jit_add_target_info ("target_feature", "sve2-sm4"); + if (TARGET_TME) + jit_add_target_info ("target_feature", "tme"); + // TODO: features dit, dpb, dpb2, flagm, lor, pan, pmuv3, ras, spe, ssbs, vh + + if (AARCH64_ISA_V8_1A) + jit_add_target_info ("target_feature", "v8.1a"); + if (AARCH64_ISA_V8_2A) + jit_add_target_info ("target_feature", "v8.2a"); + if (AARCH64_ISA_V8_3A) + jit_add_target_info ("target_feature", "v8.3a"); + if (AARCH64_ISA_V8_4A) + jit_add_target_info ("target_feature", "v8.4a"); + if (AARCH64_ISA_V8_5A) + jit_add_target_info ("target_feature", "v8.5a"); + if (AARCH64_ISA_V8_6A) + jit_add_target_info ("target_feature", "v8.6a"); + if (AARCH64_ISA_V8_7A) + jit_add_target_info ("target_feature", "v8.7a"); +} diff --git a/gcc/config/aarch64/aarch64-jit.h b/gcc/config/aarch64/aarch64-jit.h new file mode 100644 index 0000000000000..c53a509e215b2 --- /dev/null +++ b/gcc/config/aarch64/aarch64-jit.h @@ -0,0 +1,22 @@ +/* Definitions for the jit front end on the AArch64 architecture. + Copyright (C) 2024 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 +. */ + +/* Defined in aarch64-jit.cc */ +extern void aarch64_jit_register_target_info (void); + +/* Target hooks for jit language. */ +#define TARGET_JIT_REGISTER_CPU_TARGET_INFO aarch64_jit_register_target_info diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 4e801146c60a5..78a8bee023f35 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -16025,11 +16025,19 @@ aarch64_insn_cost (rtx_insn *insn, bool speed) static void aarch64_init_builtins () { + // TODO: find a better fix than this to avoid the failure: + // SET_TYPE_VECTOR_SUBPARTS, in tree.h:4258 + static bool builtins_initialized = false; + if (builtins_initialized) + return; + aarch64_general_init_builtins (); aarch64_sve::init_builtins (); #ifdef SUBTARGET_INIT_BUILTINS SUBTARGET_INIT_BUILTINS; #endif + + builtins_initialized = true; } /* Implement TARGET_FOLD_BUILTIN. */ diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 index 59571948479c0..c0d2b5413212c 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -149,6 +149,10 @@ aarch64-d.o: $(srcdir)/config/aarch64/aarch64-d.cc $(COMPILE) $< $(POSTCOMPILE) +aarch64-jit.o: $(srcdir)/config/aarch64/aarch64-jit.cc + $(COMPILE) $< + $(POSTCOMPILE) + PASSES_EXTRA += $(srcdir)/config/aarch64/aarch64-passes.def cortex-a57-fma-steering.o: $(srcdir)/config/aarch64/cortex-a57-fma-steering.cc \ diff --git a/gcc/config/default-jit.cc b/gcc/config/default-jit.cc new file mode 100644 index 0000000000000..6c76c8e0728d0 --- /dev/null +++ b/gcc/config/default-jit.cc @@ -0,0 +1,28 @@ +/* Default JIT language target hooks initializer. + Copyright (C) 2023 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm_jit.h" +#include "jit/jit-target.h" +#include "jit/jit-target-def.h" + +/* Do not include tm.h or tm_p.h here; definitions needed by the target + architecture to initialize targetjitm should instead be added to tm_jit.h. */ + +struct gcc_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 0000000000000..8e085ff45261d --- /dev/null +++ b/gcc/config/i386/i386-jit.cc @@ -0,0 +1,76 @@ +/* Subroutines for the JIT front end on the x86 architecture. + Copyright (C) 2023 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tm.h" +#include "tm_jit.h" +#include "tree.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 (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); + } + + if (float16_type_node != NULL && TYPE_PRECISION(float16_type_node) == 16) + jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_FLOAT16); + + if (float32_type_node != NULL && TYPE_PRECISION(float32_type_node) == 32) + jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_FLOAT32); + + if (float64_type_node != NULL && TYPE_PRECISION(float64_type_node) == 64) + jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_FLOAT64); + + if (float128_type_node != NULL && TYPE_PRECISION(float128_type_node) == 128) + jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_FLOAT128); + +#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 0000000000000..4f05e88003f7f --- /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 +. */ + +/* 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/i386-rust-and-jit.inc b/gcc/config/i386/i386-rust-and-jit.inc index 998f44cfa3f52..0a701a0ba179e 100644 --- a/gcc/config/i386/i386-rust-and-jit.inc +++ b/gcc/config/i386/i386-rust-and-jit.inc @@ -91,3 +91,5 @@ if (TARGET_CMPXCHG16B) ADD_TARGET_INFO ("target_feature", "cmpxchg16b"); if (TARGET_MOVBE) ADD_TARGET_INFO ("target_feature", "movbe"); +if (TARGET_80387) + ADD_TARGET_INFO ("target_feature", "x87"); diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386 index 2508f89cd06af..e5fc929c1fec5 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 0000000000000..cf8d55b8c5326 --- /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 +. */ + +#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 52df255face70..9df66da214050 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 ab6bec1f0ae78..3c1af97e2e6e3 100755 --- a/gcc/configure +++ b/gcc/configure @@ -651,6 +651,7 @@ GMPLIBS target_cpu_default rust_target_objs d_target_objs +jit_target_objs fortran_target_objs cxx_target_objs c_target_objs @@ -662,6 +663,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 @@ -15113,6 +15116,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 fca0579574fa6..26b5e13fd06f3 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2457,6 +2457,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 @@ -7546,6 +7557,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) @@ -7555,6 +7568,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 a96700c0d38ef..50e653501dad6 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 @@ -11352,6 +11360,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 eccc4d884938a..73851a1e3430d 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 @@ -7278,6 +7286,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/dwarf2asm.cc b/gcc/dwarf2asm.cc index ec5c684da4794..c467debc40ebf 100644 --- a/gcc/dwarf2asm.cc +++ b/gcc/dwarf2asm.cc @@ -1174,4 +1174,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 32dace1bfa67d..2b687055f9760 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 69e9d775d0d2c..41e6e3fd22586 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -1007,6 +1007,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/expr.cc b/gcc/expr.cc index 3815c565e2d82..0ebeb3034251a 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -14124,6 +14124,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; @@ -14165,6 +14166,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 b984bee69ea82..529417b50f224 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 59afe264a8563..0429137d694d4 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/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index e699ee5301b5b..6885f5a57f937 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -119,6 +119,14 @@ Standard types - * - :c:data:`GCC_JIT_TYPE_LONG_DOUBLE` - + * - :c:data:`GCC_JIT_TYPE_FLOAT16` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT32` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT64` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT128` + - * - :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` - C type: ``(const char *)`` * - :c:data:`GCC_JIT_TYPE_SIZE_T` @@ -430,6 +438,11 @@ Reflection API Return non-zero if the type is an integral. +.. function:: int\ + gcc_jit_type_is_floating_point (gcc_jit_type *type) + + Return non-zero if the type is floating point. + .. function:: gcc_jit_type *\ gcc_jit_type_is_pointer (gcc_jit_type *type) diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index 88784ec9e92f9..4db49710a886c 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 "c-family/c-common.h" #include "target.h" #include "jit-playback.h" #include "stor-layout.h" @@ -43,107 +44,6 @@ using namespace gcc::jit; /* Attribute handling. */ -static tree handle_alias_attribute (tree *, tree, tree, int, bool *); -static tree handle_always_inline_attribute (tree *, tree, tree, int, - bool *); -static tree handle_cold_attribute (tree *, tree, tree, int, bool *); -static tree handle_const_attribute (tree *, tree, tree, int, bool *); -static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); -static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *); -static tree handle_format_attribute (tree *, tree, tree, int, bool *); -static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); -static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); -static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); -static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); -static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); -static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); -static tree handle_novops_attribute (tree *, tree, tree, int, bool *); -static tree handle_patchable_function_entry_attribute (tree *, tree, tree, - int, bool *); -static tree handle_pure_attribute (tree *, tree, tree, int, bool *); -static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); -static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); -static tree handle_target_attribute (tree *, tree, tree, int, bool *); -static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); -static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); -static tree handle_used_attribute (tree *, tree, tree, int, bool *); -static tree handle_visibility_attribute (tree *, tree, tree, int, - bool *); -static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; - -static tree ignore_attribute (tree *, tree, tree, int, bool *); - -/* Helper to define attribute exclusions. */ -#define ATTR_EXCL(name, function, type, variable) \ - { name, function, type, variable } - -/* Define attributes that are mutually exclusive with one another. */ -static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = -{ - ATTR_EXCL ("alloc_align", true, true, true), - ATTR_EXCL ("alloc_size", true, true, true), - ATTR_EXCL ("const", true, true, true), - ATTR_EXCL ("malloc", true, true, true), - ATTR_EXCL ("pure", true, true, true), - ATTR_EXCL ("returns_twice", true, true, true), - ATTR_EXCL ("warn_unused_result", true, true, true), - ATTR_EXCL (NULL, false, false, false), -}; - -static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] = -{ - ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL (NULL, false, false, false), -}; - -/* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */ -static const struct attribute_spec::exclusions attr_alloc_exclusions[] = -{ - ATTR_EXCL ("const", true, true, true), - ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL ("pure", true, true, true), - ATTR_EXCL (NULL, false, false, false), -}; - -static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = -{ - ATTR_EXCL ("const", true, true, true), - ATTR_EXCL ("alloc_align", true, true, true), - ATTR_EXCL ("alloc_size", true, true, true), - ATTR_EXCL ("malloc", true, true, true), - ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL ("pure", true, true, true), - ATTR_EXCL (NULL, false, false, false) -}; - -static const struct attribute_spec::exclusions attr_always_inline_exclusions[] = -{ - ATTR_EXCL ("noinline", true, true, true), - ATTR_EXCL ("target_clones", true, true, true), - ATTR_EXCL (NULL, false, false, false), -}; - -extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = -{ - ATTR_EXCL ("cold", true, true, true), - ATTR_EXCL ("hot", true, true, true), - ATTR_EXCL (NULL, false, false, false) -}; - -static const struct attribute_spec::exclusions attr_noinline_exclusions[] = -{ - ATTR_EXCL ("always_inline", true, true, true), - ATTR_EXCL ("gnu_inline", true, true, true), - ATTR_EXCL (NULL, false, false, false), -}; - -static const struct attribute_spec::exclusions attr_target_exclusions[] = -{ - ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE, - TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), - ATTR_EXCL (NULL, false, false, false), -}; - /* These variables act as a cache for the target builtins. This is needed in order to be able to type-check the calls since we can only get those types in the playback phase while we need them in the recording phase. */ @@ -152,787 +52,26 @@ std::unordered_map target_function_types {}; recording::context target_builtins_ctxt{NULL}; -/* Table of machine-independent attributes supported in libgccjit. */ -static const attribute_spec jit_gnu_attributes[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, - affects_type_identity, handler, exclude } */ - { "alias", 1, 1, true, false, false, false, - handle_alias_attribute, NULL }, - { "always_inline", 0, 0, true, false, false, false, - handle_always_inline_attribute, - attr_always_inline_exclusions }, - { "cold", 0, 0, true, false, false, false, - handle_cold_attribute, - attr_cold_hot_exclusions }, - /* The same comments as for noreturn attributes apply to const ones. */ - { "const", 0, 0, true, false, false, false, - handle_const_attribute, - attr_const_pure_exclusions }, - { "fn spec", 1, 1, false, true, true, false, - handle_fnspec_attribute, NULL }, - - { "leaf", 0, 0, true, false, false, false, - handle_leaf_attribute, NULL }, - { "malloc", 0, 0, true, false, false, false, - handle_malloc_attribute, attr_alloc_exclusions }, - { "noreturn", 0, 0, true, false, false, false, - handle_noreturn_attribute, - attr_noreturn_exclusions }, - { "no vops", 0, 0, true, false, false, false, - handle_novops_attribute, NULL }, - { "noinline", 0, 0, true, false, false, false, - handle_noinline_attribute, - attr_noinline_exclusions }, - { "nonnull", 0, -1, false, true, true, false, - handle_nonnull_attribute, NULL }, - { "nothrow", 0, 0, true, false, false, false, - handle_nothrow_attribute, NULL }, - { "patchable_function_entry", 1, 2, true, false, false, false, - handle_patchable_function_entry_attribute, - NULL }, - { "pure", 0, 0, true, false, false, false, - handle_pure_attribute, - attr_const_pure_exclusions }, - { "returns_twice", 0, 0, true, false, false, false, - handle_returns_twice_attribute, - attr_returns_twice_exclusions }, - { "sentinel", 0, 1, false, true, true, false, - handle_sentinel_attribute, NULL }, - { "target", 1, -1, true, false, false, false, - handle_target_attribute, attr_target_exclusions }, - { "type generic", 0, 0, false, true, true, false, - handle_type_generic_attribute, NULL }, - { "transaction_pure", 0, 0, false, true, true, false, - handle_transaction_pure_attribute, NULL }, - { "used", 0, 0, true, false, false, false, - handle_used_attribute, NULL }, - { "visibility", 1, 1, false, false, false, false, - handle_visibility_attribute, NULL }, - { "weak", 0, 0, true, false, false, false, - handle_weak_attribute, NULL }, - /* For internal use only. The leading '*' both prevents its usage in - source code and signals that it may be overridden by machine tables. */ - { "*tm regparm", 0, 0, false, true, true, false, - ignore_attribute, NULL }, -}; - -static const scoped_attribute_specs jit_gnu_attribute_table = -{ - "gnu", { jit_gnu_attributes } -}; - -/* Give the specifications for the format attributes, used by C and all - descendants. */ - -static const attribute_spec jit_format_attributes[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, - affects_type_identity, handler, exclude } */ - { "format", 3, 3, false, true, true, false, - handle_format_attribute, NULL }, - { "format_arg", 1, 1, false, true, true, false, - handle_format_arg_attribute, NULL } -}; - -static const scoped_attribute_specs jit_format_attribute_table = -{ - "gnu", { jit_format_attributes } -}; - static const scoped_attribute_specs *const jit_attribute_table[] = { - &jit_gnu_attribute_table, - &jit_format_attribute_table + &c_common_gnu_attribute_table, + &c_common_format_attribute_table }; -/* Attribute handlers. */ - -/* Handle a "noreturn" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - tree type = TREE_TYPE (*node); - - if (TREE_CODE (*node) == FUNCTION_DECL) - TREE_THIS_VOLATILE (*node) = 1; - else if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - TREE_TYPE (*node) - = build_pointer_type - (build_type_variant (TREE_TYPE (type), - TYPE_READONLY (TREE_TYPE (type)), 1)); - else - gcc_unreachable (); - - return NULL_TREE; -} - -/* Handle a "leaf" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_leaf_attribute (tree *node, tree name, - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FUNCTION_DECL) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - if (!TREE_PUBLIC (*node)) - { - warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "const" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - tree type = TREE_TYPE (*node); - - /* See FIXME comment on noreturn in c_common_attribute_table. */ - if (TREE_CODE (*node) == FUNCTION_DECL) - TREE_READONLY (*node) = 1; - else if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - TREE_TYPE (*node) - = (build_qualified_type - (build_pointer_type - (build_type_variant (TREE_TYPE (type), 1, - TREE_THIS_VOLATILE (TREE_TYPE (type)))), - TYPE_QUALS (type))); - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - - -/* Handle a "malloc" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_malloc_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - if (TREE_CODE (*node) == FUNCTION_DECL - && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))) - DECL_IS_MALLOC (*node) = 1; - else - gcc_unreachable (); - - return NULL_TREE; -} - - -/* Handle a "pure" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_pure_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - if (TREE_CODE (*node) == FUNCTION_DECL) - DECL_PURE_P (*node) = 1; - else - gcc_unreachable (); - - return NULL_TREE; -} - - -/* Handle a "no vops" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_novops_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool *ARG_UNUSED (no_add_attrs)) -{ - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); - DECL_IS_NOVOPS (*node) = 1; - return NULL_TREE; -} - - -/* Helper for nonnull attribute handling; fetch the operand number - from the attribute argument list. */ - -static bool -get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) -{ - /* Verify the arg number is a constant. */ - if (!tree_fits_uhwi_p (arg_num_expr)) - return false; - - *valp = TREE_INT_CST_LOW (arg_num_expr); - return true; -} - -/* Handle the "nonnull" attribute. */ - -static tree -handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), - tree args, int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - tree type = *node; - - /* If no arguments are specified, all pointer arguments should be - non-null. Verify a full prototype is given so that the arguments - will have the correct types when we actually check them later. - Avoid diagnosing type-generic built-ins since those have no - prototype. */ - if (!args) - { - gcc_assert (prototype_p (type) - || !TYPE_ATTRIBUTES (type) - || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))); - - return NULL_TREE; - } - - /* Argument list specified. Verify that each argument number references - a pointer argument. */ - for (; args; args = TREE_CHAIN (args)) - { - tree argument; - unsigned HOST_WIDE_INT arg_num = 0, ck_num; - - if (!get_nonnull_operand (TREE_VALUE (args), &arg_num)) - gcc_unreachable (); - - argument = TYPE_ARG_TYPES (type); - if (argument) - { - for (ck_num = 1; ; ck_num++) - { - if (!argument || ck_num == arg_num) - break; - argument = TREE_CHAIN (argument); - } - - gcc_assert (argument - && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE); - } - } - - return NULL_TREE; -} - - -/* Handle a "nothrow" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - if (TREE_CODE (*node) == FUNCTION_DECL) - TREE_NOTHROW (*node) = 1; - else - gcc_unreachable (); - - return NULL_TREE; -} - - -/* Handle a "sentinel" attribute. */ - -static tree -handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args, - int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - gcc_assert (stdarg_p (*node)); - - if (args) - { - tree position = TREE_VALUE (args); - gcc_assert (TREE_CODE (position) == INTEGER_CST); - if (tree_int_cst_lt (position, integer_zero_node)) - gcc_unreachable (); - } - - return NULL_TREE; -} - -/* Handle a "type_generic" attribute. */ - -static tree -handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - /* Ensure we have a function type. */ - gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); - - /* Ensure we have a variadic function. */ - gcc_assert (!prototype_p (*node) || stdarg_p (*node)); - - return NULL_TREE; -} - -/* Handle a "transaction_pure" attribute. */ - -static tree -handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - /* Ensure we have a function type. */ - gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); - - return NULL_TREE; -} - -/* Handle a "returns_twice" attribute. */ - -static tree -handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); - - DECL_IS_RETURNS_TWICE (*node) = 1; - - return NULL_TREE; -} - -static tree -handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *) -{ - /* Nothing to be done here. */ - return NULL_TREE; -} - -/* Ignore the given attribute. Used when this attribute may be usefully - overridden by the target, but is not used generically. */ - -static tree -ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool *no_add_attrs) -{ - *no_add_attrs = true; - return NULL_TREE; -} - -/* Handle a "format" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool *no_add_attrs) -{ - *no_add_attrs = true; - return NULL_TREE; -} - - -/* Handle a "format_arg" attribute; arguments as in - struct attribute_spec.handler. */ - -tree -handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool *no_add_attrs) -{ - *no_add_attrs = true; - return NULL_TREE; -} - - -/* Handle a "fn spec" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name), - tree args, int ARG_UNUSED (flags), - bool *no_add_attrs ATTRIBUTE_UNUSED) -{ - gcc_assert (args - && TREE_CODE (TREE_VALUE (args)) == STRING_CST - && !TREE_CHAIN (args)); - return NULL_TREE; -} - -/* Handle an "visibility" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_visibility_attribute (tree *node, tree name, tree args, - int ARG_UNUSED (flags), - bool *ARG_UNUSED (no_add_attrs)) -{ - tree decl = *node; - tree id = TREE_VALUE (args); - enum symbol_visibility vis; - - if (TYPE_P (*node)) - { - if (TREE_CODE (*node) == ENUMERAL_TYPE) - /* OK. */; - else if (!RECORD_OR_UNION_TYPE_P (*node)) - { - warning (OPT_Wattributes, "%qE attribute ignored on non-class types", - name); - return NULL_TREE; - } - else if (TYPE_FIELDS (*node)) - { - error ("%qE attribute ignored because %qT is already defined", - name, *node); - return NULL_TREE; - } - } - else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - return NULL_TREE; - } - - if (TREE_CODE (id) != STRING_CST) - { - error ("visibility argument not a string"); - return NULL_TREE; - } - - /* If this is a type, set the visibility on the type decl. */ - if (TYPE_P (decl)) - { - decl = TYPE_NAME (decl); - if (!decl) - return NULL_TREE; - if (TREE_CODE (decl) == IDENTIFIER_NODE) - { - warning (OPT_Wattributes, "%qE attribute ignored on types", - name); - return NULL_TREE; - } - } - - if (strcmp (TREE_STRING_POINTER (id), "default") == 0) - vis = VISIBILITY_DEFAULT; - else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) - vis = VISIBILITY_INTERNAL; - else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) - vis = VISIBILITY_HIDDEN; - else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) - vis = VISIBILITY_PROTECTED; - else - { - error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs", - name, "default", "hidden", "protected", "internal"); - vis = VISIBILITY_DEFAULT; - } - - if (DECL_VISIBILITY_SPECIFIED (decl) - && vis != DECL_VISIBILITY (decl)) - { - tree attributes = (TYPE_P (*node) - ? TYPE_ATTRIBUTES (*node) - : DECL_ATTRIBUTES (decl)); - if (lookup_attribute ("visibility", attributes)) - error ("%qD redeclared with different visibility", decl); - else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES - && lookup_attribute ("dllimport", attributes)) - error ("%qD was declared %qs which implies default visibility", - decl, "dllimport"); - else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES - && lookup_attribute ("dllexport", attributes)) - error ("%qD was declared %qs which implies default visibility", - decl, "dllexport"); - } - - DECL_VISIBILITY (decl) = vis; - DECL_VISIBILITY_SPECIFIED (decl) = 1; - - /* Go ahead and attach the attribute to the node as well. This is needed - so we can determine whether we have VISIBILITY_DEFAULT because the - visibility was not specified, or because it was explicitly overridden - from the containing scope. */ - - return NULL_TREE; -} - -/* Handle a "always_inline" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_always_inline_attribute (tree *node, tree name, - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), - bool *no_add_attrs) -{ - if (TREE_CODE (*node) == FUNCTION_DECL) - { - /* Set the attribute and mark it for disregarding inline - limits. */ - DECL_DISREGARD_INLINE_LIMITS (*node) = 1; - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "cold" and attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - if (TREE_CODE (*node) == FUNCTION_DECL - || TREE_CODE (*node) == LABEL_DECL) - { - /* Attribute cold processing is done later with lookup_attribute. */ - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "noinline" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_noinline_attribute (tree *node, tree name, - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - if (TREE_CODE (*node) == FUNCTION_DECL) - DECL_UNINLINABLE (*node) = 1; - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "weak" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_weak_attribute (tree *node, tree name, - tree ARG_UNUSED (args), - int ARG_UNUSED (flags), - bool * ARG_UNUSED (no_add_attrs)) -{ - if (TREE_CODE (*node) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (*node)) - { - warning (OPT_Wattributes, "inline function %q+D declared weak", *node); - *no_add_attrs = true; - } - else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node))) - { - error ("indirect function %q+D cannot be declared weak", *node); - *no_add_attrs = true; - return NULL_TREE; - } - else if (VAR_OR_FUNCTION_DECL_P (*node)) - declare_weak (*node); - else - warning (OPT_Wattributes, "%qE attribute ignored", name); - - return NULL_TREE; -} - -/* Handle a "target" attribute. */ - -static tree -handle_target_attribute (tree *node, tree name, tree args, int flags, - bool *no_add_attrs) -{ - /* Ensure we have a function declaration. */ - if (TREE_CODE (*node) != FUNCTION_DECL) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - else if (! targetm.target_option.valid_attribute_p (*node, name, args, - flags)) - *no_add_attrs = true; - - /* Check that there's no empty string in values of the attribute. */ - for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t)) - { - tree value = TREE_VALUE (t); - if (TREE_CODE (value) == STRING_CST - && TREE_STRING_LENGTH (value) == 1 - && TREE_STRING_POINTER (value)[0] == '\0') - { - warning (OPT_Wattributes, "empty string in attribute %"); - *no_add_attrs = true; - } - } - - return NULL_TREE; -} - -/* Handle a "used" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - tree node = *pnode; - - if (TREE_CODE (node) == FUNCTION_DECL - || (VAR_P (node) && TREE_STATIC (node)) - || (TREE_CODE (node) == TYPE_DECL)) - { - TREE_USED (node) = 1; - DECL_PRESERVE_P (node) = 1; - if (VAR_P (node)) - DECL_READ_P (node) = 1; - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle an "alias" or "ifunc" attribute; arguments as in - struct attribute_spec.handler, except that IS_ALIAS tells us - whether this is an alias as opposed to ifunc attribute. */ - -static tree -handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args, - bool *no_add_attrs) -{ - tree decl = *node; - - if (TREE_CODE (decl) != FUNCTION_DECL - && (!is_alias || !VAR_P (decl))) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) - || (TREE_CODE (decl) != FUNCTION_DECL - && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) - /* A static variable declaration is always a tentative definition, - but the alias is a non-tentative definition which overrides. */ - || (TREE_CODE (decl) != FUNCTION_DECL - && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl))) - { - error ("%q+D defined both normally and as %qE attribute", decl, name); - *no_add_attrs = true; - return NULL_TREE; - } - else if (!is_alias - && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl)) - || lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))) - { - error ("weak %q+D cannot be defined %qE", decl, name); - *no_add_attrs = true; - return NULL_TREE; - } - - /* Note that the very first time we process a nested declaration, - decl_function_context will not be set. Indeed, *would* never - be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that - we do below. After such frobbery, pushdecl would set the context. - In any case, this is never what we want. */ - else if (decl_function_context (decl) == 0 && current_function_decl == NULL) - { - tree id; - - id = TREE_VALUE (args); - if (TREE_CODE (id) != STRING_CST) - { - error ("attribute %qE argument not a string", name); - *no_add_attrs = true; - return NULL_TREE; - } - id = get_identifier (TREE_STRING_POINTER (id)); - /* This counts as a use of the object pointed to. */ - TREE_USED (id) = 1; - - if (TREE_CODE (decl) == FUNCTION_DECL) - DECL_INITIAL (decl) = error_mark_node; - else - TREE_STATIC (decl) = 1; - - if (!is_alias) - { - /* ifuncs are also aliases, so set that attribute too. */ - DECL_ATTRIBUTES (decl) - = tree_cons (get_identifier ("alias"), args, - DECL_ATTRIBUTES (decl)); - DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"), - NULL, DECL_ATTRIBUTES (decl)); - } - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } +char* jit_personality_func_name = NULL; +static tree personality_decl; - if (decl_in_symtab_p (*node)) - { - struct symtab_node *n = symtab_node::get (decl); - if (n && n->refuse_visibility_changes) - error ("%+qD declared %qs after being used", - decl, is_alias ? "alias" : "ifunc"); - } +/* FIXME: This is a hack to preserve trees that we create from the + garbage collector. */ +static GTY (()) tree jit_gc_root; - return NULL_TREE; -} - -/* Handle an "alias" or "ifunc" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_alias_attribute (tree *node, tree name, tree args, - int ARG_UNUSED (flags), bool *no_add_attrs) +void +jit_preserve_from_gc (tree t) { - return handle_alias_ifunc_attribute (true, node, name, args, no_add_attrs); + jit_gc_root = tree_cons (NULL_TREE, t, jit_gc_root); } -/* (end of attribute-handling). */ - /* Language-dependent contents of a type. */ struct GTY(()) lang_type @@ -957,12 +96,13 @@ struct GTY(()) lang_identifier /* The resulting tree type. */ +/* See lang_tree_node in gcc/c/c-decl.cc. */ 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 + 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; + desc ("tree_node_structure (&%h)"))) + generic; struct lang_identifier GTY((tag ("1"))) identifier; }; @@ -1071,6 +211,8 @@ jit_end_diagnostic (diagnostic_text_output_format &, 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 ()); @@ -1091,15 +233,31 @@ jit_langhook_init (void) 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); + // FIXME: This code doesn't work as it erases the `target_builtins` map + // without checking if it's already filled before. A better check would be + // `if target_builtins.len() == 0` (or whatever this `hash_map` type method + // name is). + //static bool builtins_initialized = false; + //if (!builtins_initialized) + //{ targetm.init_builtins (); + //builtins_initialized = true; + //} return true; } @@ -1164,6 +322,10 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp) return complex_integer_type_node; } + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE + && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i))) + return FLOATN_NX_TYPE_NODE (i); /* gcc_unreachable */ return NULL; } @@ -1190,12 +352,6 @@ recording::type* tree_type_to_jit_type (tree type) // FIXME: wrong type. return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); - /* TODO: Remove when we add support for sized floating-point types. */ - for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) - if (type == FLOATN_NX_TYPE_NODE (i)) - // FIXME: wrong type. - return new recording::memento_of_get_type (&target_builtins_ctxt, - GCC_JIT_TYPE_VOID); if (type == void_type_node) return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); @@ -1261,6 +417,22 @@ recording::type* tree_type_to_jit_type (tree type) else if (type == bfloat16_type_node) return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BFLOAT16); + else if (type == float16_type_node) + { + return new recording::memento_of_get_type(&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT16); + } + else if (type == float32_type_node) + { + return new recording::memento_of_get_type(&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT32); + } + else if (type == float64_type_node) + { + return new recording::memento_of_get_type(&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT64); + } + else if (type == float128_type_node) + { + return new recording::memento_of_get_type(&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT128); + } else if (type == dfloat128_type_node) // FIXME: wrong type. return new recording::memento_of_get_type (&target_builtins_ctxt, @@ -1282,6 +454,39 @@ recording::type* tree_type_to_jit_type (tree type) return nullptr; return element_type->get_pointer (); } + else if (type == unsigned_intTI_type_node) + { + // TODO: check if this is the correct type. + return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UINT128_T); + } + else if (INTEGRAL_TYPE_P (type)) + { + // TODO: check if this is the correct type. + unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + return target_builtins_ctxt.get_int_type (size, TYPE_UNSIGNED (type)); + } + else if (SCALAR_FLOAT_TYPE_P (type)) + { + // TODO: check if this is the correct type. + unsigned int size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + enum gcc_jit_types type; + switch (size) { + case 2: + type = GCC_JIT_TYPE_FLOAT16; + break; + case 4: + type = GCC_JIT_TYPE_FLOAT32; + break; + case 8: + type = GCC_JIT_TYPE_FLOAT64; + break; + default: + fprintf (stderr, "Unexpected float size: %d\n", size); + abort (); + break; + } + return new recording::memento_of_get_type (&target_builtins_ctxt, type); + } else { // Attempt to find an unqualified type when the current type has qualifiers. @@ -1379,6 +584,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-common.h b/gcc/jit/jit-common.h index 845726b6cb34e..e32bd881b828d 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_BFLOAT16 + 1; +const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_FLOAT128 + 1; /* This comment is included by the docs. @@ -93,6 +93,21 @@ const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_BFLOAT16 + 1; End of comment for inclusion in the docs. */ +/* See c_tree_chain_next in gcc/c-family/c-common.h. */ +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 6946f100d5ccf..6901c24b14ddf 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -50,6 +50,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" @@ -294,6 +295,34 @@ get_tree_node_for_type (enum gcc_jit_types type_) return double_type_node; case GCC_JIT_TYPE_LONG_DOUBLE: return long_double_type_node; + case GCC_JIT_TYPE_FLOAT16: + if (float16_type_node == NULL || TYPE_PRECISION(float16_type_node) != 16) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_); + return NULL; + } + return float16_type_node; + case GCC_JIT_TYPE_FLOAT32: + if (float32_type_node == NULL || TYPE_PRECISION(float32_type_node) != 32) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_); + return NULL; + } + return float32_type_node; + case GCC_JIT_TYPE_FLOAT64: + if (float64_type_node == NULL || TYPE_PRECISION(float64_type_node) != 64) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_); + return NULL; + } + return float64_type_node; + case GCC_JIT_TYPE_FLOAT128: + if (float128_type_node == NULL || TYPE_PRECISION(float128_type_node) != 128) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_); + return NULL; + } + return float128_type_node; case GCC_JIT_TYPE_SIZE_T: return size_type_node; @@ -343,7 +372,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); @@ -424,7 +453,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); @@ -434,6 +464,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); @@ -441,7 +474,7 @@ new_compound_type (location *loc, } void -playback::compound_type::set_fields (const auto_vec *fields) +playback::compound_type::set_fields (const auto_vec *fields, bool is_packed) { /* Compare with c/c-decl.cc: finish_struct. */ tree t = as_tree (); @@ -458,6 +491,10 @@ playback::compound_type::set_fields (const auto_vec *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); @@ -546,6 +583,10 @@ const char* fn_attribute_to_string (gcc_jit_fn_attribute attr) return "weak"; case GCC_JIT_FN_ATTRIBUTE_NONNULL: return "nonnull"; + case GCC_JIT_FN_ATTRIBUTE_MS_ABI: + return "ms_abi"; + case GCC_JIT_FN_ATTRIBUTE_SYSV_ABI: + return "sysv_abi"; case GCC_JIT_FN_ATTRIBUTE_MAX: return NULL; } @@ -558,6 +599,8 @@ const char* variable_attribute_to_string (gcc_jit_variable_attribute attr) { case GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY: return "visibility"; + case GCC_JIT_VARIABLE_ATTRIBUTE_WEAK: + return "weak"; case GCC_JIT_VARIABLE_ATTRIBUTE_MAX: return NULL; } @@ -604,6 +647,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); @@ -742,7 +786,8 @@ global_new_decl (location *loc, const char *name, enum global_var_flags flags, const std::vector> &attributes, + std::string>> &string_attributes, + const std::vector &attributes, bool readonly) { gcc_assert (type); @@ -788,7 +833,19 @@ global_new_decl (location *loc, if (loc) set_tree_location (inner, loc); - set_variable_string_attribute (attributes, inner); + set_variable_string_attribute (string_attributes, inner); + + tree var_attributes = NULL_TREE; + for (auto attr: attributes) + { + const char* attribute = variable_attribute_to_string (attr); + if (attribute) + { + tree ident = get_identifier (attribute); + var_attributes = tree_cons (ident, NULL_TREE, var_attributes); + } + } + decl_attributes (&inner, var_attributes, 0); return inner; } @@ -835,11 +892,13 @@ new_global (location *loc, const char *name, enum global_var_flags flags, const std::vector> &attributes, + std::string>> &string_attributes, + const std::vector &attributes, bool readonly) { tree inner = - global_new_decl (loc, kind, type, name, flags, attributes, readonly); + global_new_decl (loc, kind, type, name, flags, string_attributes, + attributes, readonly); return global_finalize_lvalue (inner); } @@ -986,10 +1045,13 @@ new_global_initialized (location *loc, const char *name, enum global_var_flags flags, const std::vector> &attributes, + std::string>> &string_attributes, + const std::vector + &attributes, bool readonly) { - tree inner = global_new_decl (loc, kind, type, name, flags, attributes, readonly); + tree inner = global_new_decl (loc, kind, type, name, flags, + string_attributes, attributes, readonly); vec *constructor_elements = NULL; @@ -1923,6 +1985,10 @@ new_dereference (tree ptr, tree datum = fold_build1 (INDIRECT_REF, type, ptr); if (loc) set_tree_location (datum, loc); + if (TYPE_VOLATILE (type)) { + TREE_THIS_VOLATILE (datum) = 1; + TREE_SIDE_EFFECTS (datum) = 1; + } return datum; } @@ -2124,6 +2190,7 @@ function (context *ctxt, m_stmt_list = alloc_stmt_list (); m_stmt_iter = tsi_start (m_stmt_list); m_inner_block = make_node (BLOCK); + BLOCK_SUPERCONTEXT (m_inner_block) = m_inner_fndecl; m_inner_bind_expr = build3 (BIND_EXPR, void_type_node, NULL, m_stmt_list, m_inner_block); } @@ -2229,6 +2296,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. */ @@ -2247,6 +2323,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 ()); @@ -2348,6 +2429,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_BASIC_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 @@ -3605,6 +3750,7 @@ replay () JIT_LOG_SCOPE (get_logger ()); init_types (); + jit_target_init (); /* Replay the recorded events: */ timevar_push (TV_JIT_REPLAY); @@ -3869,7 +4015,7 @@ add_error (location *loc, const char *fmt, ...) va_list ap; va_start (ap, fmt); m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL, - fmt, ap); + DK_ERROR, fmt, ap); va_end (ap); } @@ -3881,13 +4027,12 @@ playback::context:: add_error_va (location *loc, const char *fmt, va_list ap) { m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL, - fmt, ap); + DK_ERROR, fmt, ap); } -/* Report a diagnostic up to the jit context as an error, - so that the compilation is treated as a failure. - For now, any kind of diagnostic is treated as an error by the jit - API. */ +/* Report a diagnostic up to the jit context, so that the + compilation is treated as a failure if the diagnostic + is an error. */ void playback::context:: @@ -3912,7 +4057,7 @@ add_diagnostic (const char *text, false); } - m_recording_ctxt->add_error (rec_loc, "%s", text); + m_recording_ctxt->add_diagnostic (rec_loc, diagnostic.kind, "%s", text); } /* Dealing with the linemap API. */ diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index e9a5c381959b8..64169863b010d 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 { @@ -83,7 +84,7 @@ class context : public log_user type * new_array_type (location *loc, type *element_type, - int num_elements); + unsigned long num_elements); field * new_field (location *loc, @@ -99,7 +100,8 @@ class context : public log_user 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, @@ -134,7 +136,8 @@ class context : public log_user const char *name, enum global_var_flags flags, const std::vector> &attributes, + std::string>> &string_attributes, + const std::vector &attributes, bool readonly); lvalue * @@ -149,6 +152,8 @@ class context : public log_user const std::vector> + &string_attributes, + const std::vector &attributes, bool readonly); @@ -358,7 +363,8 @@ class context : public log_user const char *name, enum global_var_flags flags, const std::vector> &attributes, + std::string>> &string_attributes, + const std::vector &attributes, bool readonly); lvalue * global_finalize_lvalue (tree inner); @@ -458,6 +464,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. @@ -518,7 +536,7 @@ class compound_type : public type : type (inner) {} - void set_fields (const auto_vec *fields); + void set_fields (const auto_vec *fields, bool is_packed); }; class field : public wrapper @@ -563,6 +581,9 @@ class function : public wrapper rvalue * get_address (location *loc); + void + set_personality_function (function *personality_function); + void build_stmt_list (); @@ -633,6 +654,12 @@ class block : public wrapper 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, @@ -696,6 +723,7 @@ class block : public wrapper public: // for now tree m_label_expr; + bool m_is_try_or_catch = false; friend class function; }; diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 8da3cb0591568..b842d901c2eaf 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -31,6 +31,14 @@ along with GCC; see the file COPYING3. If not see #include "jit-recording.h" #include "jit-playback.h" +/* This comes from diagnostic.cc. */ +static const char *const diagnostic_kind_text[] = { +#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T), +#include "diagnostic.def" +#undef DEFINE_DIAGNOSTIC_KIND + "must-not-happen" +}; + namespace gcc { namespace jit { @@ -565,6 +573,7 @@ recording::context::context (context *parent_ctxt) m_last_error_str (NULL), m_owns_last_error_str (false), m_mementos (), + m_type_mementos (), m_compound_types (), m_globals (), m_functions (), @@ -614,6 +623,10 @@ recording::context::~context () { delete m; } + FOR_EACH_VEC_ELT (m_type_mementos, i, m) + { + delete m; + } for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i) free (m_str_options[i]); @@ -647,6 +660,14 @@ recording::context::record (memento *m) m_mementos.safe_push (m); } +void +recording::context::record_type (memento *m) +{ + gcc_assert (m); + + m_type_mementos.safe_push (m); +} + /* Replay this context (and any parents) into the given replayer. */ void @@ -678,6 +699,25 @@ recording::context::replay_into (replayer *r) return; /* Replay this context's saved operations into r. */ + + FOR_EACH_VEC_ELT (m_type_mementos, i, m) + { + /* Disabled low-level debugging, here if we need it: print what + we're replaying. + Note that the calls to get_debug_string might lead to more + mementos being created for the strings. + This can also be used to exercise the debug_string + machinery. */ + if (0) + printf ("context %p replaying (%p): %s\n", + (void *)this, (void *)m, m->get_debug_string ()); + + m->replay_into (r); + + if (r->errors_occurred ()) + return; + } + FOR_EACH_VEC_ELT (m_mementos, i, m) { /* Disabled low-level debugging, here if we need it: print what @@ -717,6 +757,11 @@ recording::context::disassociate_from_playback () if (m_parent_ctxt) m_parent_ctxt->disassociate_from_playback (); + FOR_EACH_VEC_ELT (m_type_mementos, i, m) + { + m->set_playback_obj (NULL); + } + FOR_EACH_VEC_ELT (m_mementos, i, m) { m->set_playback_obj (NULL); @@ -782,7 +827,7 @@ recording::context::get_type (enum gcc_jit_types kind) else { recording::type *result = new memento_of_get_type (this, kind); - record (result); + record_type (result); m_basic_types[kind] = result; } } @@ -847,7 +892,7 @@ 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 (!s->get_fields ()) @@ -860,7 +905,7 @@ recording::context::new_array_type (recording::location *loc, } recording::type *result = new recording::array_type (this, loc, element_type, num_elements); - record (result); + record_type (result); return result; } @@ -877,7 +922,7 @@ recording::context::new_field (recording::location *loc, { recording::field *result = new recording::field (this, loc, type, new_string (name)); - record (result); + record_type (result); return result; } @@ -910,7 +955,7 @@ recording::context::new_struct_type (recording::location *loc, const char *name) { recording::struct_ *result = new struct_ (this, loc, new_string (name)); - record (result); + record_type (result); m_compound_types.safe_push (result); return result; } @@ -926,7 +971,7 @@ recording::context::new_union_type (recording::location *loc, const char *name) { recording::union_ *result = new union_ (this, loc, new_string (name)); - record (result); + record_type (result); m_compound_types.safe_push (result); return result; } @@ -950,7 +995,7 @@ recording::context::new_function_type (recording::type *return_type, param_types, is_variadic, is_target_builtin); - record (fn_type); + record_type (fn_type); return fn_type; } @@ -1677,15 +1722,44 @@ 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. */ +void +recording::context::add_diagnostic (location *loc, diagnostic_t diagnostic_kind, + const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + add_error_va (loc, diagnostic_kind, fmt, ap); + va_end (ap); +} + void recording::context::add_error (location *loc, const char *fmt, ...) { va_list ap; va_start (ap, fmt); - add_error_va (loc, fmt, ap); + add_error_va (loc, DK_ERROR, fmt, ap); va_end (ap); } @@ -1693,7 +1767,8 @@ recording::context::add_error (location *loc, const char *fmt, ...) it to stderr, and add it to the context. */ void -recording::context::add_error_va (location *loc, const char *fmt, va_list ap) +recording::context::add_error_va (location *loc, diagnostic_t diagnostic_kind, + const char *fmt, va_list ap) { int len; char *malloced_msg; @@ -1714,7 +1789,8 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap) has_ownership = true; } if (get_logger ()) - get_logger ()->log ("error %i: %s", m_error_count, errmsg); + get_logger ()->log ("%s %i: %s", diagnostic_kind_text[diagnostic_kind], + m_error_count, errmsg); const char *ctxt_progname = get_str_option (GCC_JIT_STR_OPTION_PROGNAME); @@ -1726,13 +1802,15 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap) if (print_errors_to_stderr) { if (loc) - fprintf (stderr, "%s: %s: error: %s\n", + fprintf (stderr, "%s: %s: %s: %s\n", ctxt_progname, loc->get_debug_string (), + diagnostic_kind_text[diagnostic_kind], errmsg); else - fprintf (stderr, "%s: error: %s\n", + fprintf (stderr, "%s: %s: %s\n", ctxt_progname, + diagnostic_kind_text[diagnostic_kind], errmsg); } @@ -1748,7 +1826,8 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap) m_last_error_str = const_cast (errmsg); m_owns_last_error_str = has_ownership; - m_error_count++; + if (diagnostic_kind == DK_ERROR) + m_error_count++; } /* Get the message for the first error that occurred on this context, or @@ -2144,6 +2223,8 @@ recording::context::dump_reproducer_to_file (const char *path) r.write (" /* Replay of API calls for %s. */\n", r.get_identifier (contexts[ctxt_idx])); + FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_type_mementos, i, m) + m->write_reproducer (r); FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m) m->write_reproducer (r); } @@ -2448,7 +2529,7 @@ recording::type::get_pointer () if (!m_pointer_to_this_type) { m_pointer_to_this_type = new memento_of_get_pointer (this); - m_ctxt->record (m_pointer_to_this_type); + m_ctxt->record_type (m_pointer_to_this_type); } return m_pointer_to_this_type; } @@ -2462,7 +2543,7 @@ recording::type * recording::type::get_const () { recording::type *result = new memento_of_get_const (this); - m_ctxt->record (result); + m_ctxt->record_type (result); return result; } @@ -2475,7 +2556,7 @@ recording::type * recording::type::get_restrict () { recording::type *result = new memento_of_get_restrict (this); - m_ctxt->record (result); + m_ctxt->record_type (result); return result; } @@ -2488,7 +2569,7 @@ recording::type * recording::type::get_volatile () { recording::type *result = new memento_of_get_volatile (this); - m_ctxt->record (result); + m_ctxt->record_type (result); return result; } @@ -2502,10 +2583,16 @@ recording::type::get_aligned (size_t alignment_in_bytes) { recording::type *result = new memento_of_get_aligned (this, alignment_in_bytes); - m_ctxt->record (result); + m_ctxt->record_type (result); 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 @@ -2516,7 +2603,7 @@ recording::type::get_vector (size_t num_units) { recording::type *result = new vector_type (this, num_units); - m_ctxt->record (result); + m_ctxt->record_type (result); return result; } @@ -2584,7 +2671,7 @@ recording::memento_of_get_type::get_size () break; case GCC_JIT_TYPE_FLOAT: m = targetm.c.mode_for_floating_type (TI_FLOAT_TYPE); - size = GET_MODE_PRECISION (m).to_constant (); + size = GET_MODE_UNIT_SIZE (m) * BITS_PER_UNIT; break; #ifdef HAVE_BFmode case GCC_JIT_TYPE_BFLOAT16: @@ -2592,14 +2679,53 @@ recording::memento_of_get_type::get_size () #endif case GCC_JIT_TYPE_DOUBLE: m = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE); - size = GET_MODE_PRECISION (m).to_constant (); + size = GET_MODE_UNIT_SIZE (m) * BITS_PER_UNIT; break; case GCC_JIT_TYPE_LONG_DOUBLE: m = targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE); - size = GET_MODE_PRECISION (m).to_constant (); + size = GET_MODE_UNIT_SIZE (m) * BITS_PER_UNIT; + break; + case GCC_JIT_TYPE_FLOAT16: + size = 16; + break; + case GCC_JIT_TYPE_FLOAT32: + size = 32; + break; + case GCC_JIT_TYPE_FLOAT64: + size = 64; + break; + case GCC_JIT_TYPE_FLOAT128: + size = 128; break; case GCC_JIT_TYPE_SIZE_T: - size = MAX_BITS_PER_WORD; + /* Compare with tree.cc's build_common_tree_nodes. */ + if (strcmp (SIZE_TYPE, "unsigned int") == 0) + size = INT_TYPE_SIZE; + else if (strcmp (SIZE_TYPE, "long unsigned int") == 0) + size = LONG_TYPE_SIZE; + else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0) + size = LONG_LONG_TYPE_SIZE; + else if (strcmp (SIZE_TYPE, "short unsigned int") == 0) + size = SHORT_TYPE_SIZE; + else + { + int i; + + for (i = 0; i < NUM_INT_N_ENTS; i++) + if (int_n_enabled_p[i]) + { + fprintf (stderr, "%d\n", i); + char name[50], altname[50]; + sprintf (name, "__int%d unsigned", int_n_data[i].bitsize); + sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize); + + if (strcmp (name, SIZE_TYPE) == 0 || strcmp (altname, SIZE_TYPE) == 0) + { + return int_n_data[i].bitsize / BITS_PER_UNIT; + } + } + gcc_unreachable (); + } break; default: /* As this function is called by @@ -2654,6 +2780,10 @@ recording::memento_of_get_type::dereference () case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: case GCC_JIT_TYPE_COMPLEX_FLOAT: case GCC_JIT_TYPE_COMPLEX_DOUBLE: case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: @@ -2719,6 +2849,10 @@ recording::memento_of_get_type::is_int () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return false; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2778,6 +2912,10 @@ recording::memento_of_get_type::is_signed () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2838,6 +2976,10 @@ recording::memento_of_get_type::is_float () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return true; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2902,6 +3044,10 @@ recording::memento_of_get_type::is_bool () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return false; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2979,8 +3125,11 @@ 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 */ + "bfloat16", /* GCC_JIT_TYPE_BFLOAT16 */ + "_Float16", /* GCC_JIT_TYPE_FLOAT16 */ + "_Float32", /* GCC_JIT_TYPE_FLOAT32 */ + "_Float64", /* GCC_JIT_TYPE_FLOAT64 */ + "__float128", /* GCC_JIT_TYPE_FLOAT128 */ }; /* Implementation of recording::memento::make_debug_string for @@ -3027,6 +3176,10 @@ static const char * const get_type_enum_strings[] = { "GCC_JIT_TYPE_INT64_T", "GCC_JIT_TYPE_INT128_T", "GCC_JIT_TYPE_BFLOAT16", + "GCC_JIT_TYPE_FLOAT16", + "GCC_JIT_TYPE_FLOAT32", + "GCC_JIT_TYPE_FLOAT64", + "GCC_JIT_TYPE_FLOAT128", }; void @@ -3327,7 +3480,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); } @@ -3343,7 +3496,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), @@ -3715,7 +3868,7 @@ recording::compound_type::set_fields (location *loc, gcc_assert (m_fields == NULL); m_fields = new fields (this, num_fields, field_array); - m_ctxt->record (m_fields); + m_ctxt->record_type (m_fields); } /* Implementation of pure virtual hook recording::type::dereference for @@ -3747,7 +3900,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 * @@ -3801,7 +3955,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 @@ -3872,7 +4027,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 @@ -3960,6 +4115,13 @@ recording::rvalue::access_field (recording::location *loc, return result; } +void +recording::rvalue::set_type (type *new_type) +{ + gcc_assert (new_type); + m_type = new_type; +} + /* Create a recording::dereference_field_rvalue instance and add it to the rvalue's context's list of mementos. @@ -4249,6 +4411,12 @@ void recording::lvalue::add_string_attribute ( m_string_attributes.push_back (std::make_pair (attribute, std::string (value))); } +void recording::lvalue::add_attribute ( + gcc_jit_variable_attribute attribute) +{ + m_attributes.push_back (attribute); +} + /* The implementation of class gcc::jit::recording::param. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -4396,6 +4564,36 @@ recording::function::replay_into (replayer *r) 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 the functions's context's list of mementos, and to the function's list of locals. @@ -4589,6 +4787,13 @@ recording::function::validate () /* Iteratively walk the graph of blocks, marking their "m_is_reachable" flag, starting at the initial block. */ auto_vec worklist (m_blocks.length ()); + 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) { @@ -4749,6 +4954,8 @@ static const char * const fn_attribute_reproducer_strings[] = "GCC_JIT_FN_ATTRIBUTE_CONST", "GCC_JIT_FN_ATTRIBUTE_WEAK", "GCC_JIT_FN_ATTRIBUTE_NONNULL", + "GCC_JIT_FN_ATTRIBUTE_MS_ABI", + "GCC_JIT_FN_ATTRIBUTE_SYSV_ABI", }; std::string @@ -4849,6 +5056,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. @@ -5242,6 +5474,7 @@ recording::global::replay_into (replayer *r) playback_string (m_name), m_flags, m_string_attributes, + m_attributes, m_readonly) : r->new_global (playback_location (r, m_loc), m_kind, @@ -5249,6 +5482,7 @@ recording::global::replay_into (replayer *r) playback_string (m_name), m_flags, m_string_attributes, + m_attributes, m_readonly); if (m_tls_model != GCC_JIT_TLS_MODEL_NONE) @@ -5317,6 +5551,7 @@ recording::global::write_to_dump (dump &d) if (attribute) d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str()); } + // TODO: handle m_attributes. d.write ("%s %s", m_type->get_debug_string (), get_debug_string ()); @@ -5389,6 +5624,7 @@ static const char * const tls_model_enum_strings[] = { static const char * const gcc_jit_variable_attribute_enum_strings[] = { "GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY", + "GCC_JIT_VARIABLE_ATTRIBUTE_WEAK", }; void @@ -5425,6 +5661,7 @@ recording::global::write_reproducer (reproducer &r) id, gcc_jit_variable_attribute_enum_strings[std::get<0>(attribute)], std::get<1>(attribute).c_str()); + // TODO: handle m_attributes. if (m_readonly) r.write (" gcc_jit_global_set_readonly (%s /* gcc_jit_lvalue *lvalue */);\n", @@ -7354,6 +7591,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 @@ -7392,6 +7640,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 0ac9245c2df5d..436434360cf15 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "jit-common.h" #include "jit-logging.h" +#include "diagnostic-core.h" #include "libgccjit.h" #include @@ -83,6 +84,7 @@ class context : public log_user get_builtins_manager (); void record (memento *m); + void record_type (memento *m); void replay_into (replayer *r); void disassociate_from_playback (); @@ -104,7 +106,7 @@ class context : public log_user type * new_array_type (location *loc, type *element_type, - int num_elements); + unsigned long num_elements); field * new_field (location *loc, @@ -328,13 +330,22 @@ class context : public log_user compile_to_file (enum gcc_jit_output_kind output_kind, const char *output_path); + void + get_target_info (); + + void + add_diagnostic (location *loc, diagnostic_t diagnostic_kind, + const char *fmt, ...) + GNU_PRINTF(4, 5); + void add_error (location *loc, const char *fmt, ...) GNU_PRINTF(3, 4); void - add_error_va (location *loc, const char *fmt, va_list ap) - GNU_PRINTF(3, 0); + add_error_va (location *loc, diagnostic_t diagnostic_kind, const char *fmt, + va_list ap) + GNU_PRINTF(4, 0); const char * get_first_error () const; @@ -402,6 +413,7 @@ class context : public log_user /* Recorded API usage. */ auto_vec m_mementos; + auto_vec m_type_mementos; /* Specific recordings, for use by dump_to_file. */ auto_vec m_compound_types; @@ -592,6 +604,8 @@ class type : public memento 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. @@ -623,8 +637,7 @@ class type : public memento virtual bool is_same_type_as (type *other) { - if (is_int () - && other->is_int () + if ((is_int () && other->is_int () || is_float() && other->is_float()) && get_size () == other->get_size () && is_signed () == other->is_signed ()) { @@ -673,9 +686,13 @@ class type : public memento 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; }; @@ -713,6 +730,21 @@ class memento_of_get_type : public type return type::accepts_writes_from (rtype); } + bool is_same_type_as (type *other) final override + { + if (m_kind == GCC_JIT_TYPE_VOID_PTR) + { + if (other->is_pointer ()) + { + /* LHS (this) is type (void *), and the RHS is a pointer: + accept it: */ + return true; + } + } + + return type::is_same_type_as (other); + } + bool is_int () const final override; bool is_float () const final override; bool is_bool () const final override; @@ -745,7 +777,7 @@ class memento_of_get_pointer : public type type* copy (context* ctxt) final override { type* result = new memento_of_get_pointer (m_other_type->copy (ctxt)); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -806,16 +838,10 @@ class memento_of_get_const : public decorated_type memento_of_get_const (type *other_type) : decorated_type (other_type) {} - bool accepts_writes_from (type */*rtype*/) final override - { - /* Can't write to a "const". */ - return false; - } - type* copy (context* ctxt) final override { type* result = new memento_of_get_const (m_other_type->copy (ctxt)); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -855,7 +881,7 @@ class memento_of_get_volatile : public decorated_type type* copy (context* ctxt) final override { type* result = new memento_of_get_volatile (m_other_type->copy (ctxt)); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -888,7 +914,7 @@ class memento_of_get_restrict : public decorated_type type* copy (context* ctxt) final override { type* result = new memento_of_get_restrict (m_other_type->copy (ctxt)); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -929,7 +955,7 @@ class memento_of_get_aligned : public decorated_type { type* result = new memento_of_get_aligned (m_other_type->copy (ctxt), m_alignment_in_bytes); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -978,7 +1004,7 @@ class vector_type : public decorated_type type* copy (context* ctxt) final override { type* result = new vector_type (m_other_type->copy (ctxt), m_num_units); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -996,7 +1022,7 @@ class vector_type : public decorated_type if (other_vec_type == NULL) return false; return get_num_units () == other_vec_type->get_num_units () - && get_element_type () == other_vec_type->get_element_type (); + && get_element_type ()->is_same_type_as(other_vec_type->get_element_type ()); } vector_type *is_vector () final override { return this; } @@ -1015,7 +1041,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), @@ -1039,7 +1065,7 @@ class array_type : public type { type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt), m_num_elements); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -1048,10 +1074,11 @@ class array_type : public type 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; + void set_loc(location * loc) { m_loc = loc; } private: string * make_debug_string () final override; @@ -1060,7 +1087,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 @@ -1089,7 +1116,7 @@ class function_type : public type m_param_types.length (), new_params.address (), m_is_variadic, m_is_target_builtin); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -1142,6 +1169,7 @@ class field : public memento compound_type * get_container () const { return m_container; } void set_container (compound_type *c) { m_container = c; } + void set_loc (location * loc) { m_loc = loc; } void replay_into (replayer *) override; @@ -1216,6 +1244,7 @@ class compound_type : public type bool is_signed () const final override { return false; } bool has_known_size () const final override { return m_fields != NULL; } + void set_loc (location * loc) { m_loc = loc; } playback::compound_type * playback_compound_type () @@ -1243,7 +1272,7 @@ class struct_ : public compound_type type* copy (context* ctxt) final override { type* result = new struct_ (ctxt, m_loc, m_name); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -1297,7 +1326,7 @@ class union_ : public compound_type type* copy (context* ctxt) final override { type* result = new union_ (ctxt, m_loc, m_name); - ctxt->record (result); + ctxt->record_type (result); return result; } @@ -1357,12 +1386,14 @@ class rvalue : public memento } location * get_loc () const { return m_loc; } + void set_loc (location * loc) { m_loc = loc; } /* Get the recording::type of this rvalue. Implements the post-error-checking part of gcc_jit_rvalue_get_type. */ type * get_type () const { return m_type; } + void set_type (type * new_type); playback::rvalue * playback_rvalue () const @@ -1424,7 +1455,8 @@ class lvalue : public rvalue m_reg_name (NULL), m_tls_model (GCC_JIT_TLS_MODEL_NONE), m_alignment (0), - m_string_attributes () + m_string_attributes (), + m_attributes () {} playback::lvalue * @@ -1446,6 +1478,7 @@ class lvalue : public rvalue const char *access_as_rvalue (reproducer &r) override; void add_string_attribute (gcc_jit_variable_attribute attribute, const char* value); + void add_attribute (gcc_jit_variable_attribute attribute); bool get_readonly () const { @@ -1473,6 +1506,7 @@ class lvalue : public rvalue unsigned m_alignment; std::vector> m_string_attributes; + std::vector m_attributes; bool m_readonly = false; }; @@ -1553,6 +1587,7 @@ class function : public memento new_block (const char *name); location *get_loc () const { return m_loc; } + void set_loc (location * loc) { m_loc = loc; } type *get_return_type () const { return m_return_type; } string * get_name () const { return m_name; } const vec &get_params () const { return m_params; } @@ -1571,6 +1606,7 @@ class function : public memento 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); @@ -1623,6 +1659,12 @@ class block : public memento 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, @@ -1681,6 +1723,7 @@ class block : public memento bool validate (); location *get_loc () const; + void set_loc (location * loc); statement *get_first_statement () const; statement *get_last_statement () const; @@ -1866,6 +1909,27 @@ class memento_of_new_string_literal : public rvalue 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: @@ -2027,7 +2091,7 @@ class comparison : public rvalue else inner_type = element_type; m_type = new vector_type (inner_type, vec_type->get_num_units ()); - ctxt->record (m_type); + ctxt->record_type (m_type); } } @@ -2469,6 +2533,7 @@ class statement : public memento block *get_block () const { return m_block; } location *get_loc () const { return m_loc; } + void set_loc (location * loc) { m_loc = loc; } protected: statement (block *b, location *loc) @@ -2506,6 +2571,31 @@ class eval : public statement 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 0000000000000..dcb342fafe7d6 --- /dev/null +++ b/gcc/jit/jit-target-def.h @@ -0,0 +1,20 @@ +/* jit-target-def.h -- Default initializers for jit target hooks. + Copyright (C) 2023 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not see + . */ + +#include "jit/jit-target-hooks-def.h" +#include "tree.h" +#include "hooks.h" diff --git a/gcc/jit/jit-target.cc b/gcc/jit/jit-target.cc new file mode 100644 index 0000000000000..bc1ecd5e5b463 --- /dev/null +++ b/gcc/jit/jit-target.cc @@ -0,0 +1,88 @@ +/* jit-target.cc -- Target interface for the jit front end. + Copyright (C) 2023 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" + +#include "tree.h" +#include "memmodel.h" +#include "fold-const.h" +#include "stor-layout.h" +#include "tm.h" +#include "tm_p.h" +#include "target.h" +#include "calls.h" + +#include "jit-target.h" + +#include + +static target_info jit_target_info; + +/* Initialize all variables of the Target structure. */ + +void +jit_target_init () +{ + /* Initialize target info tables, the keys required by the language are added + last, so that the OS and CPU handlers can override. */ + targetjitm.jit_register_cpu_target_info (); + targetjitm.jit_register_os_target_info (); +} + +/* Add all target info in HANDLERS to JIT_TARGET_INFO for use by + jit_has_target_value(). */ + +void +jit_add_target_info (const char *key, const char *value) +{ + if (jit_target_info.m_info.find (key) == jit_target_info.m_info.end()) + jit_target_info.m_info.insert ({key, {value}}); + else + jit_target_info.m_info[key].insert(value); +} + +void +jit_target_set_arch (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 0000000000000..3d60b01ac13bf --- /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 + . */ + +/* 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 0000000000000..061a50183953a --- /dev/null +++ b/gcc/jit/jit-target.h @@ -0,0 +1,70 @@ +/* jit-target.h -- Data structure definitions for target-specific jit behavior. + Copyright (C) 2023 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not see + . */ + +#ifndef GCC_JIT_TARGET_H +#define GCC_JIT_TARGET_H + +#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME; +#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS; +#define DEFHOOK_UNDOC DEFHOOK +#define HOOKSTRUCT(FRAGMENT) FRAGMENT + +#include "jit-target.def" +#include "libgccjit.h" + +#include +#include +#include + +static size_t hash_cstr(const char *s) +{ + const size_t seed = 0; + return std::_Hash_bytes(s, std::strlen(s), seed); +} + +struct CStringHash { + size_t operator()(const char* const &string) const { + auto res = hash_cstr (string); + return res; + } +}; + +struct CStringEqual { + bool operator()(const char* const &string1, const char* const &string2) const { + return strcmp (string1, string2) == 0; + } +}; + +struct target_info { + public: + bool has_target_value (const char *key, const char *value); + + std::unordered_map, CStringHash, CStringEqual> m_info; + std::string m_arch; + std::unordered_set 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++.h b/gcc/jit/libgccjit++.h index 7ecd915cddbb3..fdbd3decc8d80 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -1768,6 +1768,12 @@ rvalue::get_type () return type (gcc_jit_rvalue_get_type (get_inner_rvalue ())); } +inline void +rvalue::set_type (type *new_type) +{ + gcc_jit_rvalue_set_type (get_inner_rvalue (), new_type); +} + inline rvalue rvalue::access_field (field field, location loc) diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 725a5d53d06fc..6c3ff9dbaaf51 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 { }; @@ -336,7 +341,7 @@ jit_error (gcc::jit::recording::context *ctxt, va_start (ap, fmt); if (ctxt) - ctxt->add_error_va (loc, fmt, ap); + ctxt->add_error_va (loc, DK_ERROR, fmt, ap); else { /* No context? Send to stderr. */ @@ -631,6 +636,23 @@ gcc_jit_type_is_integral (gcc_jit_type *type) return type->is_int (); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_float method, in + jit-recording.cc. */ + +int +gcc_jit_type_is_floating_point (gcc_jit_type *type) +{ + RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type"); + + if (type->is_vector()) + return false; + + return type->is_float (); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the @@ -776,7 +798,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 ()); @@ -1972,6 +1994,20 @@ gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue) return static_cast (rvalue->get_type ()); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::rvalue::set_type method, in + jit-recording.h. */ + +void +gcc_jit_rvalue_set_type (gcc_jit_rvalue *rvalue, gcc_jit_type *new_type) +{ + RETURN_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); + + rvalue->set_type (new_type); +} + /* Verify that NUMERIC_TYPE is non-NULL, and that it is a "numeric" type i.e. it satisfies gcc::jit::type::is_numeric (), such as the result of gcc_jit_context_get_type (GCC_JIT_TYPE_INT). */ @@ -2290,7 +2326,7 @@ gcc_jit_context_new_comparison (gcc_jit_context *ctxt, RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); RETURN_NULL_IF_FAIL_PRINTF4 ( - a->get_type ()->unqualified () == b->get_type ()->unqualified (), + compatible_types(a->get_type()->unqualified(), b->get_type()->unqualified()), ctxt, loc, "mismatching types for comparison:" " a: %s (type: %s) b: %s (type: %s)", @@ -2497,10 +2533,10 @@ is_valid_cast (gcc::jit::recording::type *src_type, if (dst_is_int || dst_is_bool) return true; - /* Permit casts between pointer types. */ + /* Permit casts between pointer types and integers and pointers. */ gcc::jit::recording::type *deref_src_type = src_type->is_pointer (); gcc::jit::recording::type *deref_dst_type = dst_type->is_pointer (); - if (deref_src_type && deref_dst_type) + if ((deref_src_type || src_is_int) && (deref_dst_type || dst_is_int)) return true; return false; @@ -3004,6 +3040,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 @@ -3794,6 +3888,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 @@ -3900,6 +4015,45 @@ gcc_jit_context_set_output_ident (gcc_jit_context *ctxt, ctxt->set_output_ident (output_ident); } +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. After error-checking, the real work is done by the @@ -4252,6 +4406,31 @@ gcc_jit_lvalue_add_string_attribute (gcc_jit_lvalue *variable, variable->add_string_attribute (attribute, value); } +void +gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable, + gcc_jit_variable_attribute attribute) +{ + RETURN_IF_FAIL (variable, NULL, NULL, "NULL variable"); + RETURN_IF_FAIL (variable->is_global () || variable->is_local (), + NULL, + NULL, + "variable should be a variable"); + RETURN_IF_FAIL ((attribute >= 0 && attribute < GCC_JIT_VARIABLE_ATTRIBUTE_MAX), + NULL, + NULL, + "attribute should be a `gcc_jit_variable_attribute` enum value"); + + variable->add_attribute (attribute); +} + +void +gcc_jit_type_set_packed (gcc_jit_type *type) +{ + RETURN_IF_FAIL (type, NULL, NULL, "NULL type"); + + type->set_packed (); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the @@ -4655,3 +4834,46 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt, RETURN_IF_FAIL (asm_stmts, ctxt, NULL, "NULL asm_stmts"); ctxt->add_top_level_asm (loc, asm_stmts); } + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, this calls the trivial + gcc::jit::recording::field::set_loc method, in jit-recording.h. */ + +void +gcc_jit_field_set_location (gcc_jit_field *field, + gcc_jit_location *loc) +{ + RETURN_IF_FAIL (field, NULL, NULL, "NULL field"); + + field->set_loc (loc); +} + + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, this calls the trivial + gcc::jit::recording::rvalue::set_loc method , in jit-recording.h. */ + +void +gcc_jit_rvalue_set_location (gcc_jit_rvalue *rvalue, + gcc_jit_location *loc) +{ + RETURN_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); + + rvalue->set_loc (loc); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, this calls the trivial + gcc::jit::recording::function::set_loc method, in jit-recording.h. */ + +void +gcc_jit_function_set_location (gcc_jit_function *func, + gcc_jit_location *loc) +{ + RETURN_IF_FAIL (func, NULL, NULL, "NULL func"); + + func->set_loc (loc); +} diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index bc9fcaee2453d..17bd85f920f2d 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -57,6 +57,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. @@ -615,6 +618,10 @@ enum gcc_jit_types GCC_JIT_TYPE_INT128_T, GCC_JIT_TYPE_BFLOAT16, + GCC_JIT_TYPE_FLOAT16, + GCC_JIT_TYPE_FLOAT32, + GCC_JIT_TYPE_FLOAT64, + GCC_JIT_TYPE_FLOAT128, }; extern gcc_jit_type * @@ -671,7 +678,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. */ @@ -1086,6 +1093,9 @@ gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue); extern gcc_jit_type * gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue); +extern void +gcc_jit_rvalue_set_type (gcc_jit_rvalue *rvalue, gcc_jit_type *new_type); + /* Integer constants. */ extern gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt, @@ -1499,6 +1509,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. @@ -1896,6 +1938,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 @@ -2072,6 +2120,10 @@ gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, extern int gcc_jit_type_is_integral (gcc_jit_type *type); +/* Return non-zero if the type is floating point */ +extern int +gcc_jit_type_is_floating_point(gcc_jit_type * type); + /* Return the type pointed by the pointer type or NULL if it's not a * pointer. */ extern gcc_jit_type * @@ -2117,6 +2169,10 @@ enum gcc_jit_fn_attribute GCC_JIT_FN_ATTRIBUTE_WEAK, GCC_JIT_FN_ATTRIBUTE_NONNULL, + // x86 attributes. + GCC_JIT_FN_ATTRIBUTE_MS_ABI, + GCC_JIT_FN_ATTRIBUTE_SYSV_ABI, + /* Maximum value of this enum, should always be last. */ GCC_JIT_FN_ATTRIBUTE_MAX, }; @@ -2142,6 +2198,7 @@ gcc_jit_function_add_integer_array_attribute ( enum gcc_jit_variable_attribute { GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY, + GCC_JIT_VARIABLE_ATTRIBUTE_WEAK, /* Maximum value of this enum, should always be last. */ GCC_JIT_VARIABLE_ATTRIBUTE_MAX, @@ -2159,6 +2216,41 @@ gcc_jit_context_set_output_ident (gcc_jit_context *ctxt, #define LIBGCCJIT_HAVE_gcc_jit_context_set_output_ident +/* Add an attribute to a variable. */ +extern void +gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable, + enum gcc_jit_variable_attribute attribute); + +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); + +/* Given type "T", get type "T __attribute__ ((packed))". */ +extern void +gcc_jit_type_set_packed (gcc_jit_type *type); + +extern void +gcc_jit_field_set_location (gcc_jit_field *field, + gcc_jit_location *loc); +extern void +gcc_jit_function_set_location (gcc_jit_function *func, + gcc_jit_location *loc); +extern void +gcc_jit_rvalue_set_location (gcc_jit_rvalue *rvalue, + gcc_jit_location *loc); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index fcb6e6f2a55d5..f14c2017ac648 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -325,3 +325,51 @@ LIBGCCJIT_ABI_34 { global: gcc_jit_context_set_output_ident; } LIBGCCJIT_ABI_33; + +LIBGCCJIT_ABI_35 { + global: + gcc_jit_type_set_packed; +} LIBGCCJIT_ABI_34; + +LIBGCCJIT_ABI_36 { + global: + gcc_jit_block_add_try_catch; + gcc_jit_block_add_try_finally; + gcc_jit_function_set_personality_function; +} LIBGCCJIT_ABI_35; + +LIBGCCJIT_ABI_37 { + global: + gcc_jit_set_global_personality_function_name; +} LIBGCCJIT_ABI_36; + +LIBGCCJIT_ABI_38 { + 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_37; + +LIBGCCJIT_ABI_39 { + global: + gcc_jit_field_set_location; + gcc_jit_function_set_location; + gcc_jit_rvalue_set_location; +} LIBGCCJIT_ABI_38; + +LIBGCCJIT_ABI_40 { + global: + gcc_jit_type_is_floating_point; +} LIBGCCJIT_ABI_39; + +LIBGCCJIT_ABI_41 { + global: + gcc_jit_rvalue_set_type; +} LIBGCCJIT_ABI_40; + +LIBGCCJIT_ABI_42 { + global: + gcc_jit_lvalue_add_attribute; +} LIBGCCJIT_ABI_41; diff --git a/gcc/sort.cc b/gcc/sort.cc index 215d0b31d0ca3..e3eb952158afc 100644 --- a/gcc/sort.cc +++ b/gcc/sort.cc @@ -293,7 +293,8 @@ gcc_sort_r (void *vbase, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data) if (buf != scratch) free (buf); #if CHECKING_P - qsort_chk (vbase, n, size, cmp, data); + // FIXME: LTO in rustc_codegen_gcc should work even with this check enabled. + //qsort_chk (vbase, n, size, cmp, data); #endif } diff --git a/gcc/testsuite/c-c++-common/analyzer/asm-x86-dyndbg-2.c b/gcc/testsuite/c-c++-common/analyzer/asm-x86-dyndbg-2.c index db77ce9a4f96b..b5948069ec424 100644 --- a/gcc/testsuite/c-c++-common/analyzer/asm-x86-dyndbg-2.c +++ b/gcc/testsuite/c-c++-common/analyzer/asm-x86-dyndbg-2.c @@ -6,7 +6,7 @@ /* { dg-additional-options "-fdump-analyzer-untracked" } */ /* Adapted from various files in the Linux kernel, all of which have: */ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ typedef struct {} atomic_t; diff --git a/gcc/testsuite/c-c++-common/analyzer/taint-assert-BUG_ON.c b/gcc/testsuite/c-c++-common/analyzer/taint-assert-BUG_ON.c index 328940d29839b..150729531b4e2 100644 --- a/gcc/testsuite/c-c++-common/analyzer/taint-assert-BUG_ON.c +++ b/gcc/testsuite/c-c++-common/analyzer/taint-assert-BUG_ON.c @@ -3,7 +3,7 @@ /* { dg-additional-options " -ftrack-macro-expansion=0" } */ /* Adapted from code in the Linux kernel, which has this: */ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #define __noreturn __attribute__ ((__noreturn__)) diff --git a/gcc/testsuite/gcc.dg/analyzer/asm-x86-dyndbg-1.c b/gcc/testsuite/gcc.dg/analyzer/asm-x86-dyndbg-1.c index 9ea86206fd807..f31edb68ebfeb 100644 --- a/gcc/testsuite/gcc.dg/analyzer/asm-x86-dyndbg-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/asm-x86-dyndbg-1.c @@ -6,7 +6,7 @@ /* { dg-additional-options "-fdump-analyzer-untracked" } */ /* Adapted from various files in the Linux kernel, all of which have: */ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ typedef struct { int counter; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index add5619aebd4b..92249f5c866b8 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -155,6 +155,13 @@ #undef create_code #undef verify_code +/* test-const-pointer-argument.c */ +#define create_code create_code_const_pointer_argument +#define verify_code verify_code_const_pointer_argument +#include "test-const-pointer-argument.c" +#undef create_code +#undef verify_code + /* test-debug-strings.c */ #define create_code create_code_debug_strings #define verify_code verify_code_debug_strings @@ -544,6 +551,9 @@ const struct testcase testcases[] = { {"convert_vector", create_code_convert_vector, verify_code_convert_vector}, + {"const_pointer_argument", + create_code_const_pointer_argument, + verify_code_const_pointer_argument}, {"debug_strings", create_code_debug_strings, verify_code_debug_strings}, diff --git a/gcc/testsuite/jit.dg/test-const-pointer-argument.c b/gcc/testsuite/jit.dg/test-const-pointer-argument.c new file mode 100644 index 0000000000000..1c4231d735655 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-const-pointer-argument.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + void test_ptr(const void* value) + { + return; + } + + void main (void) + { + const void *ptr; + test_ptr (ptr); + return; + } + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *real_void_ptr_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR); + gcc_jit_type *const_real_void_ptr_type = + gcc_jit_type_get_const (real_void_ptr_type); + + /* Build the test_ptr. */ + gcc_jit_param *param = + gcc_jit_context_new_param (ctxt, NULL, const_real_void_ptr_type, "value"); + gcc_jit_function *test_ptr = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_ptr", + 1, ¶m, + 0); + gcc_jit_block *block = gcc_jit_function_new_block (test_ptr, NULL); + gcc_jit_block_end_with_void_return (block, NULL); + + /* Build main. */ + gcc_jit_function *main = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "main", + 0, NULL, + 0); + gcc_jit_block *main_block = gcc_jit_function_new_block (main, NULL); + + gcc_jit_type *void_ptr_type = + gcc_jit_type_get_pointer (void_type); + gcc_jit_type *const_void_ptr_type = + gcc_jit_type_get_const (void_ptr_type); + + gcc_jit_lvalue *pointer = + gcc_jit_function_new_local (main, NULL, const_void_ptr_type, "ptr"); + gcc_jit_rvalue *ptr_rvalue = gcc_jit_lvalue_as_rvalue (pointer); + + gcc_jit_block_add_eval (main_block, NULL, + gcc_jit_context_new_call (ctxt, NULL, test_ptr, 1, &ptr_rvalue)); + gcc_jit_block_end_with_void_return (main_block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); +} diff --git a/gcc/testsuite/jit.dg/test-error-array-bounds.c b/gcc/testsuite/jit.dg/test-error-array-bounds.c index a0dead13cb749..fb5c20641773e 100644 --- a/gcc/testsuite/jit.dg/test-error-array-bounds.c +++ b/gcc/testsuite/jit.dg/test-error-array-bounds.c @@ -64,11 +64,7 @@ create_code (gcc_jit_context *ctxt, void *user_data) void verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) { - /* Verify that the diagnostic led to the context failing... */ - CHECK_VALUE (result, NULL); - - /* ...and that the message was captured by the API. */ - CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), - "array subscript 10 is above array bounds of" - " 'char[10]' [-Warray-bounds=]"); + /* Verify that the message was captured by the API. */ + CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), + "while referencing 'buffer'"); } diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c index afa76ff81f6cf..85c8039133117 100644 --- a/gcc/testsuite/jit.dg/test-reflection.c +++ b/gcc/testsuite/jit.dg/test-reflection.c @@ -24,11 +24,52 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type); CHECK (!gcc_jit_type_is_integral(double_type)); + CHECK (gcc_jit_type_is_floating_point(double_type)); + + gcc_jit_type *float_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); + CHECK (!gcc_jit_type_is_bool(float_type)); + CHECK (!gcc_jit_type_is_integral(float_type)); + CHECK (gcc_jit_type_is_floating_point(float_type)); + + gcc_jit_target_info *target_info = gcc_jit_context_get_target_info(ctxt); + if (target_info != NULL && gcc_jit_target_info_supports_target_dependent_type(target_info, GCC_JIT_TYPE_FLOAT16)) + { + gcc_jit_type *float16_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT16); + CHECK (!gcc_jit_type_is_bool(float16_type)); + CHECK (!gcc_jit_type_is_integral(float16_type)); + CHECK (gcc_jit_type_is_floating_point(float16_type)); + } + + if (target_info != NULL && gcc_jit_target_info_supports_target_dependent_type(target_info, GCC_JIT_TYPE_FLOAT32)) + { + gcc_jit_type *float32_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT32); + CHECK (!gcc_jit_type_is_bool(float32_type)); + CHECK (!gcc_jit_type_is_integral(float32_type)); + CHECK (gcc_jit_type_is_floating_point(float32_type)); + } + + if (target_info != NULL && gcc_jit_target_info_supports_target_dependent_type(target_info, GCC_JIT_TYPE_FLOAT64)) + { + gcc_jit_type *float64_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT64); + CHECK (!gcc_jit_type_is_bool(float64_type)); + CHECK (!gcc_jit_type_is_integral(float64_type)); + CHECK (gcc_jit_type_is_floating_point(float64_type)); + } + + if (target_info != NULL && gcc_jit_target_info_supports_target_dependent_type(target_info, GCC_JIT_TYPE_FLOAT128)) + { + gcc_jit_type *float128_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT128); + CHECK (!gcc_jit_type_is_bool(float128_type)); + CHECK (!gcc_jit_type_is_integral(float128_type)); + CHECK (gcc_jit_type_is_floating_point(float128_type)); + } gcc_jit_type *bool_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL); CHECK (gcc_jit_type_is_bool(bool_type)); CHECK (!gcc_jit_type_is_integral(bool_type)); + CHECK (!gcc_jit_type_is_floating_point(bool_type)); gcc_jit_type *aligned_bool_type = gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8); @@ -42,15 +83,19 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) gcc_jit_type *int64 = gcc_jit_context_get_int_type(ctxt, 8, 1); CHECK (gcc_jit_type_is_integral(int64)); + CHECK (!gcc_jit_type_is_floating_point(int64)); gcc_jit_type *uint64 = gcc_jit_context_get_int_type(ctxt, 8, 0); CHECK (gcc_jit_type_is_integral(uint64)); + CHECK (!gcc_jit_type_is_floating_point(uint64)); gcc_jit_type *int8 = gcc_jit_context_get_int_type(ctxt, 1, 1); CHECK (gcc_jit_type_is_integral(int8)); + CHECK (!gcc_jit_type_is_floating_point(int8)); gcc_jit_type *uint8 = gcc_jit_context_get_int_type(ctxt, 1, 0); CHECK (gcc_jit_type_is_integral(uint8)); + CHECK (!gcc_jit_type_is_floating_point(uint8)); CHECK (!gcc_jit_type_dyncast_vector(double_type)); gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4); diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c index 8573711cf8eba..b21a5e81dc537 100644 --- a/gcc/testsuite/jit.dg/test-types.c +++ b/gcc/testsuite/jit.dg/test-types.c @@ -51,6 +51,10 @@ struct zoo float m_float; double m_double; long double m_long_double; + _Float16 m_float16; + _Float32 m_float32; + _Float64 m_float64; + __float128 m_float128; const char *m_const_char_ptr; @@ -157,6 +161,11 @@ create_code (gcc_jit_context *ctxt, void *user_data) gcc_jit_field *field_m_long_double = CREATE_FIELD (GCC_JIT_TYPE_LONG_DOUBLE, "m_long_double"); + gcc_jit_field *field_m_float16 = CREATE_FIELD(GCC_JIT_TYPE_FLOAT16, "m_float16"); + gcc_jit_field *field_m_float32 = CREATE_FIELD(GCC_JIT_TYPE_FLOAT32, "m_float32"); + gcc_jit_field *field_m_float64 = CREATE_FIELD(GCC_JIT_TYPE_FLOAT64, "m_float64"); + gcc_jit_field *field_m_float128 = CREATE_FIELD(GCC_JIT_TYPE_FLOAT128, "m_float128"); + gcc_jit_field *field_m_const_char_ptr = CREATE_FIELD (GCC_JIT_TYPE_CONST_CHAR_PTR, "m_const_char_ptr"); @@ -210,6 +219,11 @@ create_code (gcc_jit_context *ctxt, void *user_data) field_m_double, field_m_long_double, + field_m_float16, + field_m_float32, + field_m_float64, + field_m_float128, + field_m_const_char_ptr, field_m_size_t, @@ -399,6 +413,27 @@ create_code (gcc_jit_context *ctxt, void *user_data) gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG_DOUBLE), 3.141)) + ASSIGN(field_m_float16, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT16), + 3.141)) + ASSIGN(field_m_float32, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT32), + 3.141)) + ASSIGN(field_m_float64, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT64), + 3.141)) + ASSIGN(field_m_float128, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT128), + 3.141)) + ASSIGN(field_m_const_char_ptr, gcc_jit_context_new_rvalue_from_ptr ( ctxt, @@ -480,6 +515,11 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) CHECK_VALUE (z.m_double, 3.141); CHECK_VALUE (z.m_long_double, 3.141); + CHECK_VALUE (z.m_float16, (_Float16)3.141); + CHECK_VALUE (z.m_float32, (_Float32)3.141); + CHECK_VALUE (z.m_float64, (_Float64)3.141); + CHECK_VALUE (z.m_float128, (__float128)3.141); + CHECK_VALUE (z.m_const_char_ptr, test_string); CHECK_VALUE (z.m_size_t, sizeof (struct zoo)); @@ -497,6 +537,11 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BFLOAT16)), sizeof (__bfloat16)); #endif + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT16)), sizeof(_Float16)); + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT32)), sizeof(_Float32)); + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT64)), sizeof(_Float64)); + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT128)), sizeof(__float128)); + gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *array_type1 = gcc_jit_context_new_array_type (ctxt, NULL, int_type, 2); gcc_jit_type *array_type2 = gcc_jit_context_new_array_type (ctxt, NULL, int_type, 2); diff --git a/gcc/testsuite/jit.dg/test-using-global.c b/gcc/testsuite/jit.dg/test-using-global.c index 8ac9780d2b130..9c6da9f0236b7 100644 --- a/gcc/testsuite/jit.dg/test-using-global.c +++ b/gcc/testsuite/jit.dg/test-using-global.c @@ -35,13 +35,22 @@ create_code (gcc_jit_context *ctxt, void *user_data) */ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, + GCC_JIT_TYPE_FLOAT); gcc_jit_lvalue *exported_global = gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, - int_type, + float_type, "exported_global"); + + gcc_jit_rvalue *r_exported_global = + gcc_jit_lvalue_as_rvalue (exported_global); + CHECK_VALUE (gcc_jit_rvalue_get_type (r_exported_global), float_type); + gcc_jit_rvalue_set_type (r_exported_global, int_type); + CHECK_VALUE (gcc_jit_rvalue_get_type (r_exported_global), int_type); + gcc_jit_lvalue *imported_global = gcc_jit_context_new_global (ctxt, NULL, diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 6d8b8852fb84c..7a417ef13810a 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -2430,6 +2430,7 @@ toplev::finalize (void) symtab_thunks_cc_finalize (); dwarf2cfi_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 eccfcc89da40b..2758897f79445 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -15377,6 +15377,7 @@ tree_cc_finalize (void) { clear_nonstandard_integer_type_cache (); vec_free (bitint_type_cache); + gcc_eh_personality_decl = NULL; } void diff --git a/gcc/tree.h b/gcc/tree.h index 99f2617762819..c15194b854f63 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -6795,6 +6795,7 @@ extern tree get_inner_reference (tree, poly_int64 *, poly_int64 *, 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 */ diff --git a/patches/0001-Disable-128-bit-integers-for-testing-purposes.patch b/patches/0001-Disable-128-bit-integers-for-testing-purposes.patch new file mode 100644 index 0000000000000..0aaec412dc2ce --- /dev/null +++ b/patches/0001-Disable-128-bit-integers-for-testing-purposes.patch @@ -0,0 +1,57 @@ +From 90cde0a829fd72230dcc3d57b69966e4b7c7e4e9 Mon Sep 17 00:00:00 2001 +From: Antoni Boucher +Date: Fri, 16 Feb 2024 12:04:40 -0500 +Subject: [PATCH] Disable 128-bit integers for testing purposes + +--- + gcc/config/i386/i386-jit.cc | 4 ++-- + gcc/jit/jit-playback.cc | 8 ++++---- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/gcc/config/i386/i386-jit.cc b/gcc/config/i386/i386-jit.cc +index 8e085ff4526..f839201c084 100644 +--- a/gcc/config/i386/i386-jit.cc ++++ b/gcc/config/i386/i386-jit.cc +@@ -52,11 +52,11 @@ ix86_jit_register_target_info (void) + std::string cpu = arch.substr (arg_pos, end_pos - arg_pos); + jit_target_set_arch (cpu); + +- if (targetm.scalar_mode_supported_p (TImode)) ++ /*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); +- } ++ }*/ + + if (float16_type_node != NULL && TYPE_PRECISION(float16_type_node) == 16) + jit_target_add_supported_target_dependent_type(GCC_JIT_TYPE_FLOAT16); +diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc +index 773ecebe68d..0006da73413 100644 +--- a/gcc/jit/jit-playback.cc ++++ b/gcc/jit/jit-playback.cc +@@ -249,8 +249,8 @@ get_tree_node_for_type (enum gcc_jit_types type_) + case GCC_JIT_TYPE_UINT64_T: + return uint64_type_node; + case GCC_JIT_TYPE_UINT128_T: +- if (targetm.scalar_mode_supported_p (TImode)) +- return uint128_type_node; ++ /*if (targetm.scalar_mode_supported_p (TImode)) ++ return uint128_type_node;*/ + + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); +@@ -265,8 +265,8 @@ get_tree_node_for_type (enum gcc_jit_types type_) + case GCC_JIT_TYPE_INT64_T: + return intDI_type_node; + case GCC_JIT_TYPE_INT128_T: +- if (targetm.scalar_mode_supported_p (TImode)) +- return intTI_type_node; ++ /*if (targetm.scalar_mode_supported_p (TImode)) ++ return intTI_type_node;*/ + + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); +-- +2.47.0 +