Re: [PATCH] fortran: Enable target preprocessor macros with -cpp [PR42954]
"Albert, Christopher" <[email protected]>
| Newsgroups | gmane.comp.gcc.patches,gmane.comp.gcc.fortran |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 27 Apr 2026 at 20:48, Harald Anlauf wrote: > Am 27.04.26 um 8:37 PM schrieb Andrew Pinski: >> On Thu, Apr 16, 2026 at 10:18 AM Christopher Albert <[email protected]> wrote: >>> >>> The Fortran preprocessor has never defined target-specific macros such as >>> __linux__, __unix__, __ELF__, __x86_64__, or __amd64__ that the C >>> preprocessor provides. This was caused by the TARGET_OS_CPP_BUILTINS, >>> TARGET_OBJFMT_CPP_BUILTINS, and TARGET_CPU_CPP_BUILTINS hooks being >>> disabled since 2008 (marked as "Pandora's Box") because several target >>> config headers use C-family-only functions. >>> >>> Fix by providing Fortran-compatible local helpers for >>> builtin_define_std, builtin_define_with_value, and >>> builtin_define_with_int_value (which in the C frontend live in >>> c-family/c-cppbuiltin.cc and use the C-family-only globals parse_in >>> and flag_iso), plus wrapper macros for c_dialect_cxx, flag_iso, and >>> other C-family identifiers referenced by target config headers. This >>> allows TARGET_OS_CPP_BUILTINS and TARGET_OBJFMT_CPP_BUILTINS to >>> execute in the Fortran frontend. >>> >>> Unlike the C frontend default (flag_iso=0, GNU extensions mode), the >>> Fortran wrapper sets flag_iso=1 to suppress user-namespace macros like >>> bare "unix" and "linux" that would conflict with Fortran identifiers. >>> Only the reserved-namespace forms (__unix__, __linux__, etc.) are >>> defined. Fortran has no -std=cNN equivalent to control this, so the >>> conservative choice avoids silent identifier replacement. >>> >>> For TARGET_CPU_CPP_BUILTINS, which on most architectures expands to a >>> function in a C-family-only object file (e.g., ix86_target_macros in >>> i386-c.cc), provide an x86 implementation directly in fortran/cpp.cc >>> that covers architecture identification and float-size macros. >>> ISA feature macros (__SSE__, __AVX__, etc.) are not included; if >>> needed, they could be factored out of i386-c.cc into a shared object. >>> >>> Remove the dead __attribute__((target(...))) block from >>> gfortran.dg/gomp/declare-variant-10.f90: it was guarded by >>> #if defined(__x86_64__) which was previously always false because >>> gfortran never defined these macros, and gfortran does not support >>> C-style __attribute__ syntax. >>> >>> Co-authored-by: Kai Tietz <[email protected]> >>> >>> PR fortran/42954 >>> >>> gcc/fortran/ChangeLog: >>> >>> * cpp.cc (gfc_builtin_define_std): New helper mirroring >>> builtin_define_std from c-family/c-cppbuiltin.cc. >>> (gfc_builtin_define_with_value): New helper mirroring >>> builtin_define_with_value from c-family/c-cppbuiltin.cc. >>> (gfc_define_ix86_target_macros): New function providing x86 CPU >>> identification macros for the Fortran preprocessor. >>> (gfc_darwin_cpp_builtins): New function providing Darwin platform >>> macros. >>> (cpp_define_builtins): Remove Pandora's Box FIXME. Add wrapper >>> macros for C-family functions and variables used in target config >>> headers. Set flag_iso=1 to suppress bare-name macros. Enable >>> TARGET_OS_CPP_BUILTINS and TARGET_OBJFMT_CPP_BUILTINS. Call >>> gfc_define_ix86_target_macros on x86 targets. >> >> THIS is all wrong and causes too many issues. Please revert this. > > I haven't pushed yet, so all should be fine. > >>> >>> gcc/testsuite/ChangeLog: >>> >>> * gfortran.dg/gomp/declare-variant-10.f90: Remove dead >>> __attribute__((target)) block that is now exposed by newly >>> defined target macros. >>> * gfortran.dg/pr42954-linux.f90: New test. >>> * gfortran.dg/pr42954-x86.f90: New test. >>> >>> Signed-off-by: Christopher Albert <[email protected]> >>> --- >>> gcc/fortran/cpp.cc | 178 ++++++++++++++++-- >>> .../gfortran.dg/gomp/declare-variant-10.f90 | 3 - >>> gcc/testsuite/gfortran.dg/pr42954-linux.f90 | 24 +++ >>> gcc/testsuite/gfortran.dg/pr42954-x86.f90 | 10 + >>> 4 files changed, 194 insertions(+), 21 deletions(-) >>> create mode 100644 gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> create mode 100644 gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> >>> diff --git a/gcc/fortran/cpp.cc b/gcc/fortran/cpp.cc >>> index 6b5f136e4f3..ada1bc1a211 100644 >>> --- a/gcc/fortran/cpp.cc >>> +++ b/gcc/fortran/cpp.cc >>> @@ -157,6 +157,126 @@ void pp_dir_change (cpp_reader *, const char *); >>> static int dump_macro (cpp_reader *, cpp_hashnode *, void *); >>> static void dump_queued_macros (cpp_reader *); >>> >>> +/* Fortran-local helpers that mirror builtin_define_std, >>> + builtin_define_with_value, and builtin_define_with_int_value from >>> + c-family/c-cppbuiltin.cc. Those functions use the C-family-only >>> + globals parse_in and flag_iso, so they cannot be called directly >>> + from the Fortran frontend. */ >>> + >>> +/* Given "unix", define __unix, __unix__, and (if DEFINE_USER) unix. */ >>> + >>> +static void >>> +gfc_builtin_define_std (cpp_reader *pfile, const char *macro, >>> + bool define_user) >>> +{ >>> + size_t len = strlen (macro); >>> + char *buff = (char *) alloca (len + 5); >>> + char *p = buff + 2; >>> + char *q = p + len; >>> + >>> + memcpy (p, macro, len + 1); >>> + if (!(*p == '_' && (p[1] == '_' || ISUPPER (p[1])))) >>> + { >>> + if (*p != '_') >>> + *--p = '_'; >>> + if (p[1] != '_') >>> + *--p = '_'; >>> + } >>> + cpp_define (pfile, p); >>> + >>> + if (p != buff + 2) >>> + { >>> + if (q[-1] != '_') >>> + *q++ = '_'; >>> + if (q[-2] != '_') >>> + *q++ = '_'; >>> + *q = '\0'; >>> + cpp_define (pfile, p); >>> + if (define_user) >>> + cpp_define (pfile, macro); >>> + } >>> +} >>> + >>> +/* Define MACRO to EXPANSION; if IS_STR, quote the expansion. */ >>> + >>> +static void >>> +gfc_builtin_define_with_value (cpp_reader *pfile, const char *macro, >>> + const char *expansion, int is_str) >>> +{ >>> + size_t mlen = strlen (macro); >>> + size_t elen = strlen (expansion); >>> + char *buf = (char *) alloca (mlen + elen + 4); >>> + if (is_str) >>> + sprintf (buf, "%s=\"%s\"", macro, expansion); >>> + else >>> + sprintf (buf, "%s=%s", macro, expansion); >>> + cpp_define (pfile, buf); >>> +} >>> + >>> +/* Provide x86 CPU identification macros for the Fortran preprocessor. >>> + TARGET_CPU_CPP_BUILTINS() cannot be called directly because it expands >>> + to ix86_target_macros() in i386-c.cc, which is only linked into >>> + C-family frontends. This covers architecture identification and >>> + float-size macros. ISA feature macros (__SSE__, __AVX__, etc.) and >>> + arch/tune macros (__znver4__, __skylake__, etc.) from >>> + ix86_target_macros_internal() are not included; if needed, they could >>> + be factored out of i386-c.cc into a shared object. */ >>> + >>> +#ifdef TARGET_80387 >> >> Please DON'T add target defines directly to the front-end. >> Please instead use a config file from the target instead. Like what is >> done for d, rust, etc. front-ends. >> Each target should have their a source file which does the cpp_ >> instead of inlining it in the fortran front-end. >> >> Thanks, >> Andrea > > Alright, back to Chris... > > Thanks for stepping in quickly! > > Harald > >>> +static void >>> +gfc_define_ix86_target_macros (cpp_reader *pfile) >>> +{ >>> + if (TARGET_64BIT) >>> + { >>> + cpp_assert (pfile, "cpu=x86_64"); >>> + cpp_assert (pfile, "machine=x86_64"); >>> + cpp_define (pfile, "__amd64"); >>> + cpp_define (pfile, "__amd64__"); >>> + cpp_define (pfile, "__x86_64"); >>> + cpp_define (pfile, "__x86_64__"); >>> + if (TARGET_X32) >>> + { >>> + cpp_define (pfile, "_ILP32"); >>> + cpp_define (pfile, "__ILP32__"); >>> + } >>> + } >>> + else >>> + { >>> + cpp_assert (pfile, "cpu=i386"); >>> + cpp_assert (pfile, "machine=i386"); >>> + gfc_builtin_define_std (pfile, "i386", false); >>> + cpp_define (pfile, "_ILP32"); >>> + cpp_define (pfile, "__ILP32__"); >>> + } >>> + >>> + if (!TARGET_80387) >>> + cpp_define (pfile, "_SOFT_FLOAT"); >>> + >>> + if (TARGET_LONG_DOUBLE_64) >>> + cpp_define (pfile, "__LONG_DOUBLE_64__"); >>> + >>> + if (TARGET_LONG_DOUBLE_128) >>> + cpp_define (pfile, "__LONG_DOUBLE_128__"); >>> + >>> + cpp_define_formatted (pfile, "__SIZEOF_FLOAT80__=%d", >>> + GET_MODE_SIZE (XFmode)); >>> + cpp_define (pfile, "__SIZEOF_FLOAT128__=16"); >>> +} >>> +#endif >>> + >>> +/* Provide essential Darwin platform macros for the Fortran preprocessor. >>> + The full darwin_cpp_builtins() in darwin-c.cc also defines >>> + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ and >>> + __CONSTANT_CFSTRINGS__, but those depend on functions only linked >>> + into C-family frontends. */ >>> + >>> +static void ATTRIBUTE_UNUSED >>> +gfc_darwin_cpp_builtins (cpp_reader *pfile) >>> +{ >>> + cpp_define (pfile, "__MACH__"); >>> + cpp_define (pfile, "__APPLE__"); >>> + gfc_builtin_define_with_value (pfile, "__APPLE_CC__", "1", false); >>> +} >>> >>> static void >>> cpp_define_builtins (cpp_reader *pfile) >>> @@ -177,33 +297,55 @@ cpp_define_builtins (cpp_reader *pfile) >>> if (flag_openmp) >>> cpp_define (pfile, "_OPENMP=202111"); >>> >>> - /* The defines below are necessary for the TARGET_* macros. >>> - >>> - FIXME: Note that builtin_define_std() actually is a function >>> - in c-cppbuiltin.cc which uses flags undefined for Fortran. >>> - Let's skip this for now. If needed, one needs to look into it >>> - once more. */ >>> + /* Wrapper macros for C-family identifiers used in target config >>> + headers. These allow TARGET_OS_CPP_BUILTINS and >>> + TARGET_OBJFMT_CPP_BUILTINS to compile in the Fortran frontend. */ >>> >>> # define builtin_define(TXT) cpp_define (pfile, TXT) >>> -# define builtin_define_std(TXT) >>> +# define builtin_define_std(TXT) gfc_builtin_define_std (pfile, TXT, !flag_iso) >>> +# define builtin_define_with_value(MACRO, EXPANSION, IS_STR) \ >>> + gfc_builtin_define_with_value (pfile, MACRO, EXPANSION, IS_STR) >>> +# define builtin_define_with_int_value(MACRO, VALUE) \ >>> + cpp_define_formatted (pfile, "%s=" HOST_WIDE_INT_PRINT_DEC, \ >>> + MACRO, (HOST_WIDE_INT) (VALUE)) >>> # define builtin_assert(TXT) cpp_assert (pfile, TXT) >>> +# define c_dialect_cxx() 0 >>> +# define c_dialect_objc() 0 >>> +# define preprocessing_asm_p() 0 >>> +# define preprocessing_trad_p() 0 >>> + /* Fortran has no -std=cNN flag to control this. Set to 1 (ISO mode) >>> + so that builtin_define_std() only defines reserved-namespace macros >>> + like __unix__ and __linux__, not bare "unix" or "linux" which are >>> + valid Fortran identifiers and would cause silent replacement. */ >>> +# define flag_iso 1 >>> +# define flag_isoc94 0 >>> +# define flag_isoc99 0 >>> +# define flag_isoc11 0 >>> +# define flag_isoc23 0 >>> +# define darwin_cpp_builtins(PFILE) gfc_darwin_cpp_builtins (PFILE) >>> >>> - /* FIXME: Pandora's Box >>> - Using the macros below results in multiple breakages: >>> - - mingw will fail to compile this file as dependent macros >>> - assume to be used in c-cppbuiltin.cc only. Further, they use >>> - flags only valid/defined in C (same as noted above). >>> - [config/i386/mingw32.h, config/i386/cygming.h] >>> - - other platforms (not as popular) break similarly >>> - [grep for 'builtin_define_with_int_value' in gcc/config/] >>> - >>> - TARGET_CPU_CPP_BUILTINS (); >>> TARGET_OS_CPP_BUILTINS (); >>> - TARGET_OBJFMT_CPP_BUILTINS (); */ >>> + TARGET_OBJFMT_CPP_BUILTINS (); >>> + >>> +#ifdef TARGET_80387 >>> + gfc_define_ix86_target_macros (pfile); >>> +#endif >>> >>> #undef builtin_define >>> #undef builtin_define_std >>> +#undef builtin_define_with_value >>> +#undef builtin_define_with_int_value >>> #undef builtin_assert >>> +#undef c_dialect_cxx >>> +#undef c_dialect_objc >>> +#undef preprocessing_asm_p >>> +#undef preprocessing_trad_p >>> +#undef flag_iso >>> +#undef flag_isoc94 >>> +#undef flag_isoc99 >>> +#undef flag_isoc11 >>> +#undef flag_isoc23 >>> +#undef darwin_cpp_builtins >>> } >>> >>> bool >>> diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> index 0e0ab518010..115195e1194 100644 >>> --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> @@ -64,9 +64,6 @@ contains >>> call f18 () ! { dg-final { scan-tree-dump-times "f18 \\\(\\\);" 1 "gimple" } } */ >>> end subroutine >>> >>> -#if defined(__i386__) || defined(__x86_64__) >>> - __attribute__((target ("avx512f,avx512bw"))) >>> -#endif >>> subroutine test2 () >>> !$omp target >>> call f04 () ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! ilp32 } } } } } >>> diff --git a/gcc/testsuite/gfortran.dg/pr42954-linux.f90 b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> new file mode 100644 >>> index 00000000000..bd5efe7a237 >>> --- /dev/null >>> +++ b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> @@ -0,0 +1,24 @@ >>> +! { dg-do preprocess { target *-*-linux* } } >>> +! { dg-options "-cpp" } >>> +! >>> +! PR fortran/42954 - target macros missing in gfortran -cpp >>> + >>> +#ifndef __linux__ >>> +# error __linux__ not defined >>> +#endif >>> + >>> +#ifndef __linux >>> +# error __linux not defined >>> +#endif >>> + >>> +#ifndef __unix__ >>> +# error __unix__ not defined >>> +#endif >>> + >>> +#ifndef __unix >>> +# error __unix not defined >>> +#endif >>> + >>> +#ifndef __ELF__ >>> +# error __ELF__ not defined >>> +#endif >>> diff --git a/gcc/testsuite/gfortran.dg/pr42954-x86.f90 b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> new file mode 100644 >>> index 00000000000..0a3b7eac8a2 >>> --- /dev/null >>> +++ b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> @@ -0,0 +1,10 @@ >>> +! { dg-do preprocess { target { i?86-*-* x86_64-*-* } } } >>> +! { dg-options "-cpp" } >>> +! >>> +! PR fortran/42954 - target macros missing in gfortran -cpp >>> + >>> +#if !defined(__i386__) && !defined(__i386) \ >>> + && !defined(__x86_64__) && !defined(__x86_64) \ >>> + && !defined(__amd64__) && !defined(__amd64) >>> +# error x86 target macros not defined >>> +#endif >>> -- >>> 2.53.0 >>> >> Dear Andrea, thanks for checking this. I tried to keep the first version inside the Fortran frontend and overlooked the D/Rust frontend pattern you pointed out. I attached a smaller patch that adds a Fortran target hook and keeps the target-specific macro definitions in target config files. Could you check whether this structure looks right? If yes, I can extend it toward the fuller scope Harald asked for in the Bugzilla thread. Thanks, Chris
0001-fortran-add-target-hook-for-Fortran-preprocessor-mac.patch
(application/octet-stream, 33 KB)
From a81f949a9a61a47f1c6f13240c28330c4310f5fc Mon Sep 17 00:00:00 2001 From: Christopher Albert <[email protected]> Date: Tue, 28 Apr 2026 06:46:07 +0200 Subject: [PATCH] fortran: add target hook for Fortran preprocessor macros [PR42954] gfortran -E -dM has emitted no target-identification macros since 2008 because gcc/fortran/cpp.cc disabled TARGET_CPU_CPP_BUILTINS, TARGET_OS_CPP_BUILTINS, and TARGET_OBJFMT_CPP_BUILTINS. Those target macros expand into C-family-only state on many targets, so calling them from the Fortran front end is not safe. Add a small Fortran target hook vector and call one hook from the Fortran preprocessor. This keeps target-specific code out of gcc/fortran/cpp.cc and gives target maintainers a place to add Fortran-safe macros without using C-family helpers such as builtin_define_std. This first patch intentionally implements only a viable scaffold: Linux targets define the common Linux, Unix, and ELF reserved-namespace macros, and x86 targets add the basic architecture and float-size macros. Bare names such as linux and unix are not defined because they are valid Fortran identifiers. CPU feature macros, non-x86 CPU hooks, and other operating systems are left for follow-up patches. The now-reachable __attribute__((target)) block in gomp/declare-variant-10.f90 is removed because gfortran has no __attribute__ syntax; it was previously compiled out only because __i386__ and __x86_64__ were never defined by gfortran. Assisted-by: Claude (Anthropic) PR fortran/42954 gcc/ChangeLog: * Makefile.in (tm_f_file_list, tm_f_include_list): New substitution variables. (F_TARGET_DEF, F_TARGET_H): New. (TM_F_H): New. (tm_f.h, cs-tm_f.h): New rules. (fortran/f-target-hooks-def.h, s-f-target-hooks-def-h): New rules. (default-f.o): New rule. (generated_files): Add $(TM_F_H) and fortran/f-target-hooks-def.h. (s-tm-texi): Recognize fortran/f-target.def as a hook source. (build/genhooks.o): Depend on $(F_TARGET_DEF). * configure.ac: Compute tm_f_file_list and tm_f_include_list from $tm_f_file; substitute both. * configure: Regenerate. * config.gcc (target_has_targetfm): Document and initialize. (tm_f_file): New. (fortran_target_objs): Add per-target Fortran objects, linux-f.o on Linux targets, and default-f.o otherwise. * config/default-f.cc: New file. * config/i386/i386-f.cc: New file. * config/i386/i386-f.h: New file. * config/i386/t-i386 (i386-f.o): New rule. * config/linux-f.cc: New file. * config/t-linux (linux-f.o): New rule. * doc/tm.texi.in (Fortran ABI parameters): Add TARGET_F_CPP_BUILTINS. * doc/tm.texi: Regenerate. * genhooks.cc: Include fortran/f-target.def. * hooks.cc (hook_void_cpp_reader): New function. * hooks.h (hook_void_cpp_reader): Declare. gcc/fortran/ChangeLog: * cpp.cc: Include tm_f.h and fortran/f-target.h. Drop the local TARGET_CPU_CPP_BUILTINS, TARGET_OS_CPP_BUILTINS, TARGET_OBJFMT_CPP_BUILTINS, builtin_define, builtin_define_std, and builtin_assert fallback macros. (cpp_define_builtins): Call targetfm.f_cpp_builtins. * f-target-def.h: New file. * f-target.def: New file. * f-target.h: New file. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/declare-variant-10.f90: Drop dead __attribute__((target)) block. * gfortran.dg/pr42954-linux.f90: New test. * gfortran.dg/pr42954-x86.f90: New test. Signed-off-by: Christopher Albert <[email protected]> --- gcc/Makefile.in | 31 +++++++- gcc/config.gcc | 20 +++++ gcc/config/default-f.cc | 28 +++++++ gcc/config/i386/i386-f.cc | 78 +++++++++++++++++++ gcc/config/i386/i386-f.h | 25 ++++++ gcc/config/i386/t-i386 | 4 + gcc/config/linux-f.cc | 56 +++++++++++++ gcc/config/t-linux | 4 + gcc/configure | 19 ++++- gcc/configure.ac | 13 ++++ gcc/doc/tm.texi | 14 ++++ gcc/doc/tm.texi.in | 7 ++ gcc/fortran/cpp.cc | 45 ++--------- gcc/fortran/f-target-def.h | 20 +++++ gcc/fortran/f-target.def | 44 +++++++++++ gcc/fortran/f-target.h | 32 ++++++++ gcc/genhooks.cc | 1 + gcc/hooks.cc | 5 ++ gcc/hooks.h | 1 + .../gfortran.dg/gomp/declare-variant-10.f90 | 3 - gcc/testsuite/gfortran.dg/pr42954-linux.f90 | 33 ++++++++ gcc/testsuite/gfortran.dg/pr42954-x86.f90 | 11 +++ 22 files changed, 449 insertions(+), 45 deletions(-) create mode 100644 gcc/config/default-f.cc create mode 100644 gcc/config/i386/i386-f.cc create mode 100644 gcc/config/i386/i386-f.h create mode 100644 gcc/config/linux-f.cc create mode 100644 gcc/fortran/f-target-def.h create mode 100644 gcc/fortran/f-target.def create mode 100644 gcc/fortran/f-target.h create mode 100644 gcc/testsuite/gfortran.dg/pr42954-linux.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr42954-x86.f90 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 8ecef4ccdc7..dda02937dbc 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -613,6 +613,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_f_file_list=@tm_f_file_list@ +tm_f_include_list=@tm_f_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@ @@ -922,6 +924,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_F_H = tm_f.h $(tm_f_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) @@ -983,12 +986,14 @@ 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 +F_TARGET_DEF = fortran/f-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) +F_TARGET_H = fortran/f-target.h $(F_TARGET_DEF) JIT_TARGET_H = jit/jit-target.h $(JIT_TARGET_DEF) MACHMODE_H = machmode.h mode-classes.def HOOKS_H = hooks.h @@ -2137,6 +2142,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_f.h: cs-tm_f.h ; @true tm_jit.h: cs-tm_jit.h ; @true cs-config.h: Makefile @@ -2177,6 +2183,11 @@ cs-tm_rust.h: Makefile HEADERS="$(tm_rust_include_list)" DEFINES="" \ $(SHELL) $(srcdir)/mkconfig.sh tm_rust.h +cs-tm_f.h: Makefile + TARGET_CPU_DEFAULT="" \ + HEADERS="$(tm_f_include_list)" DEFINES="" \ + $(SHELL) $(srcdir)/mkconfig.sh tm_f.h + cs-tm_jit.h: Makefile TARGET_CPU_DEFAULT="" \ HEADERS="$(tm_jit_include_list)" DEFINES="" \ @@ -2655,6 +2666,12 @@ default-rust.o: config/default-rust.cc $(COMPILE) $< $(POSTCOMPILE) +# Files used by the Fortran language front end. + +default-f.o: config/default-f.cc + $(COMPILE) $< + $(POSTCOMPILE) + # Language-independent files. DRIVER_DEFINES = \ @@ -3001,6 +3018,15 @@ s-rust-target-hooks-def-h: build/genhooks$(build_exeext) rust/rust-target-hooks-def.h $(STAMP) s-rust-target-hooks-def-h +fortran/f-target-hooks-def.h: s-f-target-hooks-def-h; @true + +s-f-target-hooks-def-h: build/genhooks$(build_exeext) + $(RUN_GEN) build/genhooks$(build_exeext) "Fortran Target Hook" \ + > tmp-f-target-hooks-def.h + $(SHELL) $(srcdir)/../move-if-change tmp-f-target-hooks-def.h \ + fortran/f-target-hooks-def.h + $(STAMP) s-f-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) @@ -3035,6 +3061,7 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in || test $(srcdir)/doc/tm.texi -nt $(srcdir)/common/common-target.def \ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/d/d-target.def \ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/rust/rust-target.def \ + || test $(srcdir)/doc/tm.texi -nt $(srcdir)/fortran/f-target.def \ ); then \ echo >&2 ; \ echo You should edit $(srcdir)/doc/tm.texi.in rather than $(srcdir)/doc/tm.texi . >&2 ; \ @@ -3218,6 +3245,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_JIT_H) $(TM_H) \ gimple-match-auto.h generic-match-auto.h \ c-family/c-target-hooks-def.h d/d-target-hooks-def.h \ $(TM_RUST_H) rust/rust-target-hooks-def.h \ + $(TM_F_H) fortran/f-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 @@ -3353,7 +3381,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) $(JIT_TARGET_DEF) \ + $(COMMON_TARGET_DEF) $(D_TARGET_DEF) $(RUST_TARGET_DEF) \ + $(F_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) diff --git a/gcc/config.gcc b/gcc/config.gcc index 8fe99616f82..7214670b1d2 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -216,6 +216,9 @@ # target_has_targetrustm Set to yes or no depending on whether the target # has its own definition of targetrustm. # +# target_has_targetfm Set to yes or no depending on whether the target +# has its own definition of targetfm. +# # target_has_targetjitm Set to yes or no depending on whether the target # has its own definition of targetjitm. @@ -241,6 +244,7 @@ target_has_targetcm=no target_has_targetm_common=yes target_has_targetdm=no target_has_targetrustm=no +target_has_targetfm=no target_has_targetjitm=no tm_defines= xm_defines= @@ -642,6 +646,16 @@ then rust_target_objs="${rust_target_objs} ${cpu_type}-rust.o" fi +tm_f_file= +if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-f.h +then + tm_f_file="${cpu_type}/${cpu_type}-f.h" +fi +if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-f.cc +then + fortran_target_objs="${fortran_target_objs} ${cpu_type}-f.o" +fi + tm_jit_file= if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-jit.h then @@ -1009,6 +1023,8 @@ case ${target} in target_has_targetdm=yes rust_target_objs="${rust_target_objs} linux-rust.o" target_has_targetrustm=yes + fortran_target_objs="${fortran_target_objs} linux-f.o" + target_has_targetfm=yes ;; *-*-kfreebsd*-gnu) d_target_objs="${d_target_objs} kfreebsd-d.o" @@ -3791,6 +3807,10 @@ if [ "$target_has_targetrustm" = "no" ]; then rust_target_objs="$rust_target_objs default-rust.o" fi +if [ "$target_has_targetfm" = "no" ]; then + fortran_target_objs="$fortran_target_objs default-f.o" +fi + if [ "$target_has_targetjitm" = "no" ]; then jit_target_objs="$jit_target_objs default-jit.o" fi diff --git a/gcc/config/default-f.cc b/gcc/config/default-f.cc new file mode 100644 index 00000000000..9968fbbe513 --- /dev/null +++ b/gcc/config/default-f.cc @@ -0,0 +1,28 @@ +/* Default Fortran target hook initializer. + Copyright (C) 2026 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Do not include tm.h or tm_p.h here; definitions needed by the target + architecture to initialize targetfm should instead be added to tm_f.h. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm_f.h" +#include "fortran/f-target.h" +#include "fortran/f-target-def.h" + +struct gcc_targetfm targetfm = TARGETFM_INITIALIZER; diff --git a/gcc/config/i386/i386-f.cc b/gcc/config/i386/i386-f.cc new file mode 100644 index 00000000000..1476a4e37a6 --- /dev/null +++ b/gcc/config/i386/i386-f.cc @@ -0,0 +1,78 @@ +/* x86 support needed only by the Fortran front end. + Copyright (C) 2026 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "cpplib.h" +#include "tm_f.h" +#include "memmodel.h" +#include "tm_p.h" +#include "fortran/f-target.h" + +/* Provide the x86 portion of TARGET_F_CPP_BUILTINS. Mirrors the + architecture-identification and float-size portion of + ix86_target_macros in gcc/config/i386/i386-c.cc; ISA feature macros + (__SSE__, __AVX__, ...) and arch / tune macros (__haswell__, + __tune_*__) are intentionally out of scope and remain a follow-up + exercise. Bare-namespace macros ("i386" without underscores) are + never emitted because they would clash with valid Fortran + identifiers. */ + +void +ix86_f_cpu_cpp_builtins (cpp_reader *pfile) +{ + if (TARGET_64BIT) + { + cpp_assert (pfile, "cpu=x86_64"); + cpp_assert (pfile, "machine=x86_64"); + cpp_define (pfile, "__amd64"); + cpp_define (pfile, "__amd64__"); + cpp_define (pfile, "__x86_64"); + cpp_define (pfile, "__x86_64__"); + if (TARGET_X32) + { + cpp_define (pfile, "_ILP32"); + cpp_define (pfile, "__ILP32__"); + } + } + else + { + cpp_assert (pfile, "cpu=i386"); + cpp_assert (pfile, "machine=i386"); + cpp_define (pfile, "__i386"); + cpp_define (pfile, "__i386__"); + cpp_define (pfile, "_ILP32"); + cpp_define (pfile, "__ILP32__"); + } + + if (!TARGET_80387) + cpp_define (pfile, "_SOFT_FLOAT"); + + if (TARGET_LONG_DOUBLE_64) + cpp_define (pfile, "__LONG_DOUBLE_64__"); + + if (TARGET_LONG_DOUBLE_128) + cpp_define (pfile, "__LONG_DOUBLE_128__"); + + cpp_define_formatted (pfile, "__SIZEOF_FLOAT80__=%d", + GET_MODE_SIZE (XFmode)); + cpp_define (pfile, "__SIZEOF_FLOAT128__=16"); +} diff --git a/gcc/config/i386/i386-f.h b/gcc/config/i386/i386-f.h new file mode 100644 index 00000000000..a87aff058df --- /dev/null +++ b/gcc/config/i386/i386-f.h @@ -0,0 +1,25 @@ +/* Subroutines for the Fortran front end on the x86 architecture. + Copyright (C) 2026 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_I386_F_H +#define GCC_I386_F_H + +extern void ix86_f_cpu_cpp_builtins (cpp_reader *); + +#define TARGET_F_CPU_CPP_BUILTINS ix86_f_cpu_cpp_builtins + +#endif /* GCC_I386_F_H */ diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386 index ae0fb8ed474..f231ad14841 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-f.o: $(srcdir)/config/i386/i386-f.cc + $(COMPILE) $< + $(POSTCOMPILE) + i386-jit.o: $(srcdir)/config/i386/i386-jit.cc $(COMPILE) $< $(POSTCOMPILE) diff --git a/gcc/config/linux-f.cc b/gcc/config/linux-f.cc new file mode 100644 index 00000000000..190d33e9a47 --- /dev/null +++ b/gcc/config/linux-f.cc @@ -0,0 +1,56 @@ +/* Linux support needed only by the Fortran front end. + Copyright (C) 2026 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "cpplib.h" +#include "tm_f.h" +#include "fortran/f-target.h" +#include "fortran/f-target-def.h" + +#ifndef TARGET_F_CPU_CPP_BUILTINS +#define TARGET_F_CPU_CPP_BUILTINS(PFILE) ((void) (PFILE)) +#endif + +/* Implement TARGET_F_CPP_BUILTINS for Linux targets. This intentionally + covers only target-identity macros; option-dependent CPU feature macros + can be added by target maintainers in follow-up patches. */ + +static void +linux_f_cpp_builtins (cpp_reader *pfile) +{ + TARGET_F_CPU_CPP_BUILTINS (pfile); + + if (OPTION_GLIBC) + cpp_define (pfile, "__gnu_linux__"); + cpp_define (pfile, "__linux__"); + cpp_define (pfile, "__linux"); + cpp_define (pfile, "__unix__"); + cpp_define (pfile, "__unix"); + cpp_assert (pfile, "system=linux"); + cpp_assert (pfile, "system=unix"); + cpp_assert (pfile, "system=posix"); + + cpp_define (pfile, "__ELF__"); +} + +#undef TARGET_F_CPP_BUILTINS +#define TARGET_F_CPP_BUILTINS linux_f_cpp_builtins + +struct gcc_targetfm targetfm = TARGETFM_INITIALIZER; diff --git a/gcc/config/t-linux b/gcc/config/t-linux index 238f1f074ce..b639b78b41f 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-f.o: $(srcdir)/config/linux-f.cc + $(COMPILE) $< + $(POSTCOMPILE) diff --git a/gcc/configure b/gcc/configure index ef780a23c2f..402a68100af 100755 --- a/gcc/configure +++ b/gcc/configure @@ -662,6 +662,8 @@ xm_include_list xm_file_list tm_jit_include_list tm_jit_file_list +tm_f_include_list +tm_f_file_list tm_rust_include_list tm_rust_file_list tm_d_include_list @@ -15205,6 +15207,17 @@ for f in $tm_rust_file; do esac done +tm_f_file_list= +tm_f_include_list= +for f in $tm_f_file; do + case $f in + * ) + tm_f_file_list="${tm_f_file_list} \$(srcdir)/config/$f" + tm_f_include_list="${tm_f_include_list} config/$f" + ;; + esac +done + tm_jit_file_list= tm_jit_include_list= for f in $tm_jit_file; do @@ -21975,7 +21988,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21978 "configure" +#line 21991 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -22081,7 +22094,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 22084 "configure" +#line 22097 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -34359,6 +34372,8 @@ fi + + diff --git a/gcc/configure.ac b/gcc/configure.ac index cdf2997cb5f..85d6eef08f0 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2492,6 +2492,17 @@ for f in $tm_rust_file; do esac done +tm_f_file_list= +tm_f_include_list= +for f in $tm_f_file; do + case $f in + * ) + tm_f_file_list="${tm_f_file_list} \$(srcdir)/config/$f" + tm_f_include_list="${tm_f_include_list} config/$f" + ;; + esac +done + tm_jit_file_list= tm_jit_include_list= for f in $tm_jit_file; do @@ -7495,6 +7506,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_f_file_list) +AC_SUBST(tm_f_include_list) AC_SUBST(tm_jit_file_list) AC_SUBST(tm_jit_include_list) AC_SUBST(xm_file_list) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2832a447e3e..8661eccc403 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -56,6 +56,7 @@ through the macros defined in the @file{.h} file. * C++ ABI:: Controlling C++ ABI changes. * D Language and ABI:: Controlling D ABI changes. * Rust Language and ABI:: Controlling Rust ABI changes. +* Fortran Language and ABI:: Controlling Fortran ABI parameters. * JIT Language and ABI:: JIT ABI parameters * Named Address Spaces:: Adding support for named address spaces * Misc:: Everything else. @@ -11443,6 +11444,19 @@ Similar to @code{TARGET_RUST_CPU_INFO}, but is used for configuration info relating to the target operating system. @end deftypefn +@node Fortran Language and ABI +@section Fortran ABI parameters +@cindex parameters, fortran abi + +@deftypefn {Fortran Target Hook} void TARGET_F_CPP_BUILTINS (cpp_reader *@var{pfile}) +Define preprocessor symbols that describe the target for the Fortran +preprocessor. Implementations should call @code{cpp_define}, +@code{cpp_assert}, and @code{cpp_define_formatted} (from libcpp) directly +on @var{pfile}; they must not depend on C-family-only state such as +@code{parse_in} or @code{flag_iso}. Bare names such as @code{linux} or +@code{unix} clash with valid Fortran identifiers and must be omitted. +@end deftypefn + @node JIT Language and ABI @section JIT ABI parameters @cindex parameters, jit abi diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 274bb899d0c..c8c20b97b54 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -56,6 +56,7 @@ through the macros defined in the @file{.h} file. * C++ ABI:: Controlling C++ ABI changes. * D Language and ABI:: Controlling D ABI changes. * Rust Language and ABI:: Controlling Rust ABI changes. +* Fortran Language and ABI:: Controlling Fortran ABI parameters. * JIT Language and ABI:: JIT ABI parameters * Named Address Spaces:: Adding support for named address spaces * Misc:: Everything else. @@ -7330,6 +7331,12 @@ floating-point support; they are not included in this mechanism. @hook TARGET_RUST_OS_INFO +@node Fortran Language and ABI +@section Fortran ABI parameters +@cindex parameters, fortran abi + +@hook TARGET_F_CPP_BUILTINS + @node JIT Language and ABI @section JIT ABI parameters @cindex parameters, jit abi diff --git a/gcc/fortran/cpp.cc b/gcc/fortran/cpp.cc index 6b5f136e4f3..f2646d37d99 100644 --- a/gcc/fortran/cpp.cc +++ b/gcc/fortran/cpp.cc @@ -35,23 +35,13 @@ along with GCC; see the file COPYING3. If not see #include "incpath.h" #include "cppbuiltin.h" #include "mkdeps.h" +#include "tm_f.h" +#include "fortran/f-target.h" #ifndef TARGET_SYSTEM_ROOT # define TARGET_SYSTEM_ROOT NULL #endif -#ifndef TARGET_CPU_CPP_BUILTINS -# define TARGET_CPU_CPP_BUILTINS() -#endif - -#ifndef TARGET_OS_CPP_BUILTINS -# define TARGET_OS_CPP_BUILTINS() -#endif - -#ifndef TARGET_OBJFMT_CPP_BUILTINS -# define TARGET_OBJFMT_CPP_BUILTINS() -#endif - /* Holds switches parsed by gfc_cpp_handle_option (), but whose handling is deferred to gfc_cpp_init (). */ @@ -177,33 +167,10 @@ cpp_define_builtins (cpp_reader *pfile) if (flag_openmp) cpp_define (pfile, "_OPENMP=202111"); - /* The defines below are necessary for the TARGET_* macros. - - FIXME: Note that builtin_define_std() actually is a function - in c-cppbuiltin.cc which uses flags undefined for Fortran. - Let's skip this for now. If needed, one needs to look into it - once more. */ - -# define builtin_define(TXT) cpp_define (pfile, TXT) -# define builtin_define_std(TXT) -# define builtin_assert(TXT) cpp_assert (pfile, TXT) - - /* FIXME: Pandora's Box - Using the macros below results in multiple breakages: - - mingw will fail to compile this file as dependent macros - assume to be used in c-cppbuiltin.cc only. Further, they use - flags only valid/defined in C (same as noted above). - [config/i386/mingw32.h, config/i386/cygming.h] - - other platforms (not as popular) break similarly - [grep for 'builtin_define_with_int_value' in gcc/config/] - - TARGET_CPU_CPP_BUILTINS (); - TARGET_OS_CPP_BUILTINS (); - TARGET_OBJFMT_CPP_BUILTINS (); */ - -#undef builtin_define -#undef builtin_define_std -#undef builtin_assert + /* Provide target-specific cpp macros via a per-target hook. The hook + implementation calls cpp_define / cpp_assert directly and must not + depend on C-family-only state such as parse_in or flag_iso. */ + targetfm.f_cpp_builtins (pfile); } bool diff --git a/gcc/fortran/f-target-def.h b/gcc/fortran/f-target-def.h new file mode 100644 index 00000000000..b1747927e9e --- /dev/null +++ b/gcc/fortran/f-target-def.h @@ -0,0 +1,20 @@ +/* f-target-def.h -- Default initializers for Fortran target hooks. + Copyright (C) 2026 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "fortran/f-target-hooks-def.h" +#include "tree.h" +#include "hooks.h" diff --git a/gcc/fortran/f-target.def b/gcc/fortran/f-target.def new file mode 100644 index 00000000000..a9d86607f10 --- /dev/null +++ b/gcc/fortran/f-target.def @@ -0,0 +1,44 @@ +/* f-target.def -- Target hook definitions for the Fortran front end. + Copyright (C) 2026 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* See target-hooks-macros.h for details of macros that should be + provided by the including file, and how to use them here. */ + +#include "target-hooks-macros.h" + +#undef HOOK_TYPE +#define HOOK_TYPE "Fortran Target Hook" + +HOOK_VECTOR (TARGETFM_INITIALIZER, gcc_targetfm) + +#undef HOOK_PREFIX +#define HOOK_PREFIX "TARGET_" + +/* Target-specific preprocessor builtins. */ +DEFHOOK +(f_cpp_builtins, + "Define preprocessor symbols that describe the target for the Fortran\n\ +preprocessor. Implementations should call @code{cpp_define},\n\ +@code{cpp_assert}, and @code{cpp_define_formatted} (from libcpp) directly\n\ +on @var{pfile}; they must not depend on C-family-only state such as\n\ +@code{parse_in} or @code{flag_iso}. Bare names such as @code{linux} or\n\ +@code{unix} clash with valid Fortran identifiers and must be omitted.", + void, (cpp_reader *pfile), + hook_void_cpp_reader) + +/* Close the 'struct gcc_targetfm' definition. */ +HOOK_VECTOR_END (C90_EMPTY_HACK) diff --git a/gcc/fortran/f-target.h b/gcc/fortran/f-target.h new file mode 100644 index 00000000000..339f614c488 --- /dev/null +++ b/gcc/fortran/f-target.h @@ -0,0 +1,32 @@ +/* f-target.h -- Data structure definitions for target-specific Fortran + behavior. + Copyright (C) 2026 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_F_TARGET_H +#define GCC_F_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 "f-target.def" + +/* Each target can provide their own. */ +extern struct gcc_targetfm targetfm; + +#endif /* GCC_F_TARGET_H */ diff --git a/gcc/genhooks.cc b/gcc/genhooks.cc index 42dbace771f..cadd6dd3e9e 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 "fortran/f-target.def" #include "jit/jit-target.def" #undef DEFHOOK }; diff --git a/gcc/hooks.cc b/gcc/hooks.cc index 2b47fd3e50f..f75c7dc1bad 100644 --- a/gcc/hooks.cc +++ b/gcc/hooks.cc @@ -306,6 +306,11 @@ hook_void_constcharptr (const char *) { } +void +hook_void_cpp_reader (cpp_reader *) +{ +} + void hook_void_tree_treeptr (tree, tree *) { diff --git a/gcc/hooks.h b/gcc/hooks.h index 1ad4abb5500..2a45b3f8d91 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -82,6 +82,7 @@ extern bool hook_bool_wint_wint_uint_bool_true (const widest_int &, extern void hook_void_void (void); extern void hook_void_constcharptr (const char *); +extern void hook_void_cpp_reader (cpp_reader *); extern void hook_void_rtx_insn_int (rtx_insn *, int); extern void hook_void_FILEptr_constcharptr (FILE *, const char *); extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *, diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 index 0e0ab518010..115195e1194 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 @@ -64,9 +64,6 @@ contains call f18 () ! { dg-final { scan-tree-dump-times "f18 \\\(\\\);" 1 "gimple" } } */ end subroutine -#if defined(__i386__) || defined(__x86_64__) - __attribute__((target ("avx512f,avx512bw"))) -#endif subroutine test2 () !$omp target call f04 () ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! ilp32 } } } } } diff --git a/gcc/testsuite/gfortran.dg/pr42954-linux.f90 b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 new file mode 100644 index 00000000000..20a67f1ea5b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 @@ -0,0 +1,33 @@ +! { dg-do preprocess { target *-*-linux* } } +! { dg-options "-cpp" } +! +! PR fortran/42954 - target macros missing in gfortran -cpp + +#ifndef __linux__ +# error __linux__ not defined +#endif + +#ifndef __linux +# error __linux not defined +#endif + +#ifndef __unix__ +# error __unix__ not defined +#endif + +#ifndef __unix +# error __unix not defined +#endif + +#ifdef linux +# error bare linux should not be defined +#endif + +#ifdef unix +# error bare unix should not be defined +#endif + +#ifndef __ELF__ +# error __ELF__ not defined +#endif +end diff --git a/gcc/testsuite/gfortran.dg/pr42954-x86.f90 b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 new file mode 100644 index 00000000000..07788718286 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 @@ -0,0 +1,11 @@ +! { dg-do preprocess { target { i?86-*-* x86_64-*-* } } } +! { dg-options "-cpp" } +! +! PR fortran/42954 - target macros missing in gfortran -cpp + +#if !defined(__i386__) && !defined(__i386) \ + && !defined(__x86_64__) && !defined(__x86_64) \ + && !defined(__amd64__) && !defined(__amd64) +# error x86 target macros not defined +#endif +end -- 2.54.0