[gcc r15-385] Fortran: fix dependency checks for inquiry refs [PR115039]

2024-05-11 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:d4974fd22730014e337fd7ec2471945ba8afb00e

commit r15-385-gd4974fd22730014e337fd7ec2471945ba8afb00e
Author: Harald Anlauf 
Date:   Fri May 10 21:18:03 2024 +0200

Fortran: fix dependency checks for inquiry refs [PR115039]

gcc/fortran/ChangeLog:

PR fortran/115039
* expr.cc (gfc_traverse_expr): An inquiry ref does not constitute
a dependency and cannot collide with a symbol.

gcc/testsuite/ChangeLog:

PR fortran/115039
* gfortran.dg/statement_function_5.f90: New test.

Diff:
---
 gcc/fortran/expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/statement_function_5.f90 | 20 
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 66edad58278a..c883966646cb 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -5500,7 +5500,7 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,
  break;
 
case REF_INQUIRY:
- return true;
+ return false;
 
default:
  gcc_unreachable ();
diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 
b/gcc/testsuite/gfortran.dg/statement_function_5.f90
new file mode 100644
index ..bc5a5dba7a0f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/115039
+!
+! Check that inquiry refs work with statement functions
+!
+! { dg-additional-options "-std=legacy -fdump-tree-optimized" }
+! { dg-prune-output " Obsolescent feature" }
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
+
+program testit
+  implicit none
+  complex :: x
+  real:: im
+  integer :: slen
+  character(5) :: s
+  im(x)   = x%im + x%re + x%kind
+  slen(s) = s%len
+  if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1
+  if (slen('abcdef') /= 5)  stop 2
+end program testit


[gcc r15-384] [PATCH v4 4/4] Output S_COMPILE3 symbol in CodeView debug section

2024-05-11 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:1da83fece2963cfe0df57ac5e85dd1f92427ca70

commit r15-384-g1da83fece2963cfe0df57ac5e85dd1f92427ca70
Author: Mark Harmstone 
Date:   Sat May 11 08:24:59 2024 -0600

[PATCH v4 4/4] Output S_COMPILE3 symbol in CodeView debug section

Outputs the S_COMPILE3 symbol in the CodeView .debug$S debug section.
The DEBUG_S_SYMBOLS block added here makes up pretty much everything
that isn't data structures or line numbers; we add the S_COMPILE3 symbol
here to start it off.

This is a descriptive bit, the most interesting part of which is the
version of the compiler used.

gcc/
* dwarf2codeview.cc (DEBUG_S_SYMBOLS): Define.
(S_COMPILE3, CV_CFL_80386, CV_CFL_X64): Likewise.
(CV_CFL_C, CV_CFL_CXX): Likewise.
(SYMBOL_START_LABEL, SYMBOL_END_LABEL): Likewise.
(start_processor, language_constant): New functions.
(write_compile3_symbol, write_codeview_symbols): Likewise.
(codeview_debug_finish): Call write_codeview_symbols.

Diff:
---
 gcc/dwarf2codeview.cc | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 9c69ebf89983..db776d79be4a 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -39,14 +39,25 @@ along with GCC; see the file COPYING3.  If not see
 
 #define CV_SIGNATURE_C13   4
 
+#define DEBUG_S_SYMBOLS0xf1
 #define DEBUG_S_LINES  0xf2
 #define DEBUG_S_STRINGTABLE 0xf3
 #define DEBUG_S_FILECHKSMS  0xf4
 
 #define CHKSUM_TYPE_MD51
 
+#define S_COMPILE3 0x113c
+
+#define CV_CFL_80386   0x03
+#define CV_CFL_X64 0xD0
+
+#define CV_CFL_C   0x00
+#define CV_CFL_CXX 0x01
+
 #define LINE_LABEL "Lcvline"
 #define END_FUNC_LABEL "Lcvendfunc"
+#define SYMBOL_START_LABEL "Lcvsymstart"
+#define SYMBOL_END_LABEL   "Lcvsymend"
 
 #define HASH_SIZE 16
 
@@ -120,6 +131,7 @@ struct codeview_function
 
 static unsigned int line_label_num;
 static unsigned int func_label_num;
+static unsigned int sym_label_num;
 static codeview_source_file *files, *last_file;
 static unsigned int num_files;
 static uint32_t string_offset = 1;
@@ -592,6 +604,119 @@ codeview_end_epilogue (void)
 }
 }
 
+/* Return the CodeView constant for the selected architecture.  */
+
+static uint16_t
+target_processor (void)
+{
+  if (TARGET_64BIT)
+return CV_CFL_X64;
+  else
+return CV_CFL_80386;
+}
+
+/* Return the CodeView constant for the language being used.  */
+
+static uint32_t
+language_constant (void)
+{
+  const char *language_string = lang_hooks.name;
+
+  if (startswith (language_string, "GNU C++"))
+return CV_CFL_CXX;
+  else if (startswith (language_string, "GNU C"))
+return CV_CFL_C;
+
+  return 0;
+}
+
+/* Write a S_COMPILE3 symbol, which records the details of the compiler
+   being used.  */
+
+static void
+write_compile3_symbol (void)
+{
+  unsigned int label_num = ++sym_label_num;
+
+  static const char compiler_name[] = "GCC ";
+
+  /* This is struct COMPILESYM3 in binutils and Microsoft's cvinfo.h:
+
+ struct COMPILESYM3
+ {
+   uint16_t length;
+   uint16_t type;
+   uint32_t flags;
+   uint16_t machine;
+   uint16_t frontend_major;
+   uint16_t frontend_minor;
+   uint16_t frontend_build;
+   uint16_t frontend_qfe;
+   uint16_t backend_major;
+   uint16_t backend_minor;
+   uint16_t backend_build;
+   uint16_t backend_qfe;
+ } ATTRIBUTE_PACKED;
+  */
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+  "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+  label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_COMPILE3);
+  putc ('\n', asm_out_file);
+
+  /* Microsoft has the flags as a bitfield, with the bottom 8 bits being the
+ language constant, and the reset being MSVC-specific stuff.  */
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, language_constant ());
+  putc ('\n', asm_out_file);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, target_processor ());
+  putc ('\n', asm_out_file);
+
+  /* Write 8 uint16_ts for the frontend and backend versions.  As with GAS, we
+ zero these, as it's easier to record the version in the compiler
+ string.  */
+  for (unsigned int i = 0; i < 8; i++)
+{
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, 0);
+  putc ('\n', asm_out_file);
+}
+
+  ASM_OUTPUT_ASCII (asm_out_file, compiler_name, sizeof (compiler_name) - 1);
+  ASM_OUTPUT_ASCII (asm_out_file, version_string, strlen (version_string) + 1);
+
+  

[gcc r15-383] [PATCH v2 3/4] Output line numbers in CodeView section

2024-05-11 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:1f129e5e2b74c20a757f2809792af229b551b09b

commit r15-383-g1f129e5e2b74c20a757f2809792af229b551b09b
Author: Mark Harmstone 
Date:   Sat May 11 08:19:53 2024 -0600

[PATCH v2 3/4] Output line numbers in CodeView section

Outputs the DEBUG_S_LINES block in the CodeView .debug$S section, which
maps between line numbers and addresses.

You'll need a fairly recent version of GAS for the .secidx directive to
be recognized.

gcc/
* dwarf2codeview.cc (DEBUG_S_LINES, LINE_LABEL): Define.
(END_FUNC_LABEL): Likewise.
(struct codeview_line, codeview_line_block): New structures.
(codeview_function): Likewise.
(line_label_num, func_label_num, funcs, last_func): New variables.
(last_filename, last_file_id): Likewise.
(codeview_source_line, write_line_numbers): New functions.
(codeview_switch_text_section, codeview_end_epilogue): Likewise.
(codeview_debug_finish): Call write_line_numbers.
* dwarf2codeview.h (codeview_source_line): Prototype.
(codeview_switch_text_secction, codeview_end_epilogue): Likewise.
* dwarf2out.cc (dwarf2_end_epilogue): Add codeview support.
(dwarf2out_switch_text_section): Likewise.
(dwarf2out_source_line): Likewise.
* opts.cc (finish_options): Handle codeview debugging symbols.

Diff:
---
 gcc/dwarf2codeview.cc | 303 ++
 gcc/dwarf2codeview.h  |   3 +
 gcc/dwarf2out.cc  |  15 +++
 gcc/opts.cc   |   2 +-
 4 files changed, 322 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index da8315310b50..9c69ebf89983 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -39,11 +39,15 @@ along with GCC; see the file COPYING3.  If not see
 
 #define CV_SIGNATURE_C13   4
 
+#define DEBUG_S_LINES  0xf2
 #define DEBUG_S_STRINGTABLE 0xf3
 #define DEBUG_S_FILECHKSMS  0xf4
 
 #define CHKSUM_TYPE_MD51
 
+#define LINE_LABEL "Lcvline"
+#define END_FUNC_LABEL "Lcvendfunc"
+
 #define HASH_SIZE 16
 
 struct codeview_string
@@ -91,11 +95,128 @@ struct codeview_source_file
   uint8_t hash[HASH_SIZE];
 };
 
+struct codeview_line
+{
+  codeview_line *next;
+  unsigned int line_no;
+  unsigned int label_num;
+};
+
+struct codeview_line_block
+{
+  codeview_line_block *next;
+  uint32_t file_id;
+  unsigned int num_lines;
+  codeview_line *lines, *last_line;
+};
+
+struct codeview_function
+{
+  codeview_function *next;
+  function *func;
+  unsigned int end_label;
+  codeview_line_block *blocks, *last_block;
+};
+
+static unsigned int line_label_num;
+static unsigned int func_label_num;
 static codeview_source_file *files, *last_file;
 static unsigned int num_files;
 static uint32_t string_offset = 1;
 static hash_table *strings_htab;
 static codeview_string *strings, *last_string;
+static codeview_function *funcs, *last_func;
+static const char* last_filename;
+static uint32_t last_file_id;
+
+/* Record new line number against the current function.  */
+
+void
+codeview_source_line (unsigned int line_no, const char *filename)
+{
+  codeview_line *l;
+  uint32_t file_id = last_file_id;
+  unsigned int label_num = ++line_label_num;
+
+  targetm.asm_out.internal_label (asm_out_file, LINE_LABEL, label_num);
+
+  if (!last_func || last_func->func != cfun)
+{
+  codeview_function *f = (codeview_function *)
+   xmalloc (sizeof (codeview_function));
+
+  f->next = NULL;
+  f->func = cfun;
+  f->end_label = 0;
+  f->blocks = f->last_block = NULL;
+
+  if (!funcs)
+   funcs = f;
+  else
+   last_func->next = f;
+
+  last_func = f;
+}
+
+  if (filename != last_filename)
+{
+  codeview_source_file *sf = files;
+
+  while (sf)
+   {
+ if (!strcmp (sf->filename, filename))
+   {
+ /* 0x18 is the size of the checksum entry for each file.
+0x6 bytes for the header, plus 0x10 bytes for the hash,
+then padded to a multiple of 4.  */
+
+ file_id = sf->file_num * 0x18;
+ last_filename = filename;
+ last_file_id = file_id;
+ break;
+   }
+
+ sf = sf->next;
+   }
+}
+
+  if (!last_func->last_block || last_func->last_block->file_id != file_id)
+{
+  codeview_line_block *b;
+
+  b = (codeview_line_block *) xmalloc (sizeof (codeview_line_block));
+
+  b->next = NULL;
+  b->file_id = file_id;
+  b->num_lines = 0;
+  b->lines = b->last_line = NULL;
+
+  if (!last_func->blocks)
+   last_func->blocks = b;
+  else
+   last_func->last_block->next = b;
+
+  last_func->last_block = b;
+}
+
+  if (last_func->last_block->last_line
+&& last_func->last_block->last_line->line_no == line_no)
+return;
+
+ 

[gcc r15-382] [PATCH v2 2/4] Output file checksums in CodeView section

2024-05-11 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:ed6690a0ca911138abd4d707510fd03ef188a28b

commit r15-382-ged6690a0ca911138abd4d707510fd03ef188a28b
Author: Mark Harmstone 
Date:   Sat May 11 08:15:43 2024 -0600

[PATCH v2 2/4] Output file checksums in CodeView section

Outputs the file name and MD5 hash of the main source file into the
CodeView .debug$S section, along with that of any #include'd files.

gcc/
* dwarf2codeview.cc (DEBUG_S_STRINGTABLE): Define.
(DEBUG_S_FILECHKSMS, CHKSUM_TYPE_MD5, HASH_SIZE): Likewise.
(codeview_string, codeview_source_file): New structures.
(struct string_hasher): New class for codeview_string hashing.
(files, last_file, num_files, string_offset): New variables.
(strings_hstab, strings, last_string): Likewise.
(add_string, codevie_start_source_file): New functions.
(write_strings_tabe, write_soruce_files): Likewise.
(codeview_debug_finish): Call new functions.
* dwarf2codeview.h (codeview_start_source_file): Prototype.
* dwarf2out.cc (dwarf2out_start_source_file): Handle codeview.

Diff:
---
 gcc/dwarf2codeview.cc | 254 ++
 gcc/dwarf2codeview.h  |   1 +
 gcc/dwarf2out.cc  |   5 +
 3 files changed, 260 insertions(+)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index f08f5d55ad7c..da8315310b50 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -39,6 +39,257 @@ along with GCC; see the file COPYING3.  If not see
 
 #define CV_SIGNATURE_C13   4
 
+#define DEBUG_S_STRINGTABLE 0xf3
+#define DEBUG_S_FILECHKSMS  0xf4
+
+#define CHKSUM_TYPE_MD51
+
+#define HASH_SIZE 16
+
+struct codeview_string
+{
+  codeview_string *next;
+  uint32_t offset;
+  char *string;
+};
+
+struct string_hasher : free_ptr_hash 
+{
+  typedef const char *compare_type;
+
+  static hashval_t hash (const codeview_string *x)
+  {
+return htab_hash_string (x->string);
+  }
+
+  static bool equal (const codeview_string *x, const char *y)
+  {
+return !strcmp (x->string, y);
+  }
+
+  static void mark_empty (codeview_string *x)
+  {
+if (x->string)
+  {
+   free (x->string);
+   x->string = NULL;
+  }
+  }
+
+  static void remove (codeview_string *)
+  {
+free (x->string);
+  }
+};
+
+struct codeview_source_file
+{
+  codeview_source_file *next;
+  unsigned int file_num;
+  uint32_t string_offset;
+  char *filename;
+  uint8_t hash[HASH_SIZE];
+};
+
+static codeview_source_file *files, *last_file;
+static unsigned int num_files;
+static uint32_t string_offset = 1;
+static hash_table *strings_htab;
+static codeview_string *strings, *last_string;
+
+/* Adds string to the string table, returning its offset.  If already present,
+   this returns the offset of the existing string.  */
+
+static uint32_t
+add_string (const char *string)
+{
+  codeview_string **slot;
+  codeview_string *s;
+  size_t len;
+
+  if (!strings_htab)
+strings_htab = new hash_table (10);
+
+  slot = strings_htab->find_slot_with_hash (string, htab_hash_string (string),
+   INSERT);
+
+  if (*slot)
+return (*slot)->offset;
+
+  s = (codeview_string *) xmalloc (sizeof (codeview_string));
+  len = strlen (string);
+
+  s->next = NULL;
+
+  s->offset = string_offset;
+  string_offset += len + 1;
+
+  s->string = xstrdup (string);
+
+  if (last_string)
+last_string->next = s;
+  else
+strings = s;
+
+  last_string = s;
+
+  *slot = s;
+
+  return s->offset;
+}
+
+/* A new source file has been encountered - record the details and calculate
+   its hash.  */
+
+void
+codeview_start_source_file (const char *filename)
+{
+  codeview_source_file *sf;
+  char *path;
+  uint32_t string_offset;
+  FILE *f;
+
+  path = lrealpath (filename);
+  string_offset = add_string (path);
+  free (path);
+
+  sf = files;
+  while (sf)
+{
+  if (sf->string_offset == string_offset)
+   return;
+
+  sf = sf->next;
+}
+
+  sf = (codeview_source_file *) xmalloc (sizeof (codeview_source_file));
+  sf->next = NULL;
+  sf->file_num = num_files;
+  sf->string_offset = string_offset;
+  sf->filename = xstrdup (filename);
+
+  f = fopen (filename, "r");
+  if (!f)
+internal_error ("could not open %s for reading", filename);
+
+  if (md5_stream (f, sf->hash))
+{
+  fclose (f);
+  internal_error ("md5_stream failed");
+}
+
+  fclose (f);
+
+  if (last_file)
+last_file->next = sf;
+  else
+files = sf;
+
+  last_file = sf;
+  num_files++;
+}
+
+/* Write out the strings table into the .debug$S section.  The linker will
+   parse this, and handle the deduplication and hashing for all the object
+   files.  */
+
+static void
+write_strings_table (void)
+{
+  codeview_string *string;
+
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, DEBUG_S_STRINGTABLE);
+  putc ('\n', asm_out_file);
+
+  

[gcc r15-381] [PATCH v2 1/4] Support for CodeView debugging format

2024-05-11 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:36781ef8fd26eb9a0686957e7bac8f5ccc5ecc3f

commit r15-381-g36781ef8fd26eb9a0686957e7bac8f5ccc5ecc3f
Author: Mark Harmstone 
Date:   Sat May 11 08:08:50 2024 -0600

[PATCH v2 1/4] Support for CodeView debugging format

This patch and the following add initial support for Microsoft's
CodeView debugging format, as used by MSVC, to mingw targets.

Note that you will need a recent version of binutils for this to be
useful. The best way to view the output is to run Microsoft's
cvdump.exe, found in their microsoft-pdb repo on GitHub, against the
object files.

gcc/

* Makefile.in (OBJS): Add dwarf2codeview.o.
(GTFILES): Add dwarf2codeview.cc
* config/i386/cygming.h (CODEVIEW_DEBUGGING_INFO): Define.
* dwarf2codeview.cc: New file.
* dwarf2codeview.h: New file.
* dwarf2out.cc: Include dwarf2codeview.h.
(dwarf2out_finish): Call codeview_debug_finish as needed.
* flag-types.h (DINFO_TYPE_CODEVIEW): Add enum member.
(CODEVIEW_DEBUG): Define.
* flags.h (codeview_debuginfo_p): Proottype.
* opts.cc (debug_type_names): Add codeview.
(debug_type_masks): Add CODEVIEW_DEBUG.
(df_set_names): Add codeview.
(codeview_debuginfo_p): New function.
(dwarf_based_debuginfo_p): Add CODEVIEW clause.
(set_debug_level): Handle CODEVIEW_DEBUG.
* toplev.cc (process_options): Handle codeview.

gcc/testsuite
* gcc.dg/debug/codeview/codeview-1.c: New test.
* gcc.dg/debug/codeview/codeview.exp: New testsuite driver.

Diff:
---
 gcc/Makefile.in  |  2 +
 gcc/config/i386/cygming.h|  2 +
 gcc/dwarf2codeview.cc| 54 
 gcc/dwarf2codeview.h | 30 +
 gcc/dwarf2out.cc |  6 +++
 gcc/flag-types.h |  3 ++
 gcc/flags.h  |  4 ++
 gcc/opts.cc  | 23 +++---
 gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c |  6 +++
 gcc/testsuite/gcc.dg/debug/codeview/codeview.exp | 48 +
 gcc/toplev.cc|  4 ++
 11 files changed, 177 insertions(+), 5 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ecd511463572..a7f15694c34b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1443,6 +1443,7 @@ OBJS = \
dumpfile.o \
dwarf2asm.o \
dwarf2cfi.o \
+   dwarf2codeview.o \
dwarf2ctf.o \
dwarf2out.o \
early-remat.o \
@@ -2838,6 +2839,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h 
$(srcdir)/coretypes.h \
   $(srcdir)/dwarf2out.h \
   $(srcdir)/dwarf2asm.cc \
   $(srcdir)/dwarf2cfi.cc \
+  $(srcdir)/dwarf2codeview.cc \
   $(srcdir)/dwarf2ctf.cc \
   $(srcdir)/dwarf2out.cc \
   $(srcdir)/ctfc.h \
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index beedf7c398a5..98b375538e75 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #define DWARF2_DEBUGGING_INFO 1
 
+#define CODEVIEW_DEBUGGING_INFO 1
+
 #undef PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 
diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
new file mode 100644
index ..f08f5d55ad7c
--- /dev/null
+++ b/gcc/dwarf2codeview.cc
@@ -0,0 +1,54 @@
+/* Generate CodeView debugging info from the GCC DWARF.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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
+.  */
+
+/* See gas/codeview.h in binutils for more about the constants and structs
+   listed below.  References to Microsoft files refer to Microsoft's PDB
+   repository: https://github.com/microsoft/microsoft-pdb.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "errors.h"
+#include "md5.h"
+#include "function.h"
+#include "version.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "dwarf2out.h"
+#include "dwarf2codeview.h"
+
+#ifdef CODEVIEW_DEBUGGING_INFO
+
+#define CV_SIGNATURE_C13   4
+
+/* Finish CodeView debug 

[gcc r15-380] tree-optimization/114760 - check variants of >> and << in loop-niter

2024-05-11 Thread Di Zhao via Gcc-cvs
https://gcc.gnu.org/g:1b0919cd147a2b6ccdee2b1217bf0200bdcc87aa

commit r15-380-g1b0919cd147a2b6ccdee2b1217bf0200bdcc87aa
Author: dzhao.ampere 
Date:   Fri May 10 11:55:18 2024 +0800

tree-optimization/114760 - check variants of >> and << in loop-niter

When recognizing bit counting idiom, include pattern "x * 2"
for "x << 1", and "x / 2" for "x >> 1" (given x is unsigned).

gcc/ChangeLog:
PR tree-optimization/114760
* tree-ssa-loop-niter.cc (is_lshift_by_1): New function
to check if STMT is equivalent to x << 1.
(is_rshift_by_1): New function to check if STMT is
equivalent to x >> 1.
(number_of_iterations_cltz): Enhance the identification
of logical shift by one.
(number_of_iterations_cltz_complement): Enhance the
identification of logical shift by one.

gcc/testsuite/ChangeLog:
PR tree-optimization/114760
* gcc.dg/tree-ssa/pr114760-1.c: New test.
* gcc.dg/tree-ssa/pr114760-2.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/pr114760-1.c | 69 ++
 gcc/testsuite/gcc.dg/tree-ssa/pr114760-2.c | 20 +
 gcc/tree-ssa-loop-niter.cc | 56 ++--
 3 files changed, 131 insertions(+), 14 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr114760-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr114760-1.c
new file mode 100644
index ..9f10ccc3b510
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr114760-1.c
@@ -0,0 +1,69 @@
+/* PR tree-optimization/114760 */
+/* { dg-do compile } */
+/* { dg-require-effective-target clz } */
+/* { dg-require-effective-target ctz } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+unsigned
+ntz32_1 (unsigned x)
+{
+  int n = 32;
+  while (x != 0)
+{
+  n = n - 1;
+  x = x * 2;
+}
+  return n;
+}
+
+unsigned
+ntz32_2 (unsigned x)
+{
+  int n = 32;
+  while (x != 0)
+{
+  n = n - 1;
+  x = x + x;
+}
+  return n;
+}
+
+unsigned
+ntz32_3 (unsigned x)
+{
+  int n = 32;
+  while (x != 0)
+{
+  n = n - 1;
+  x = x << 1;
+}
+  return n;
+}
+
+#define PREC (__CHAR_BIT__ * __SIZEOF_INT__)
+int
+nlz32_1 (unsigned int b) {
+int c = PREC;
+
+while (b != 0) {
+   b >>= 1;
+   c --;
+}
+
+return c;
+}
+
+int
+nlz32_2 (unsigned int b) {
+int c = PREC;
+
+while (b != 0) {
+   b /= 2;
+   c --;
+}
+
+return c;
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_ctz|\\.CTZ" 3 "optimized" } } 
*/
+/* { dg-final { scan-tree-dump-times "__builtin_clz|\\.CLZ" 2 "optimized" } } 
*/
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr114760-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr114760-2.c
new file mode 100644
index ..e1b4c4b13382
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr114760-2.c
@@ -0,0 +1,20 @@
+/* PR tree-optimization/114760 */
+/* { dg-do compile } */
+/* { dg-require-effective-target clz } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+// Check that for signed type, there's no CLZ.
+#define PREC (__CHAR_BIT__ * __SIZEOF_INT__)
+int
+no_nlz32 (int b) {
+int c = PREC;
+
+while (b != 0) {
+   b /= 2;
+   c --;
+}
+
+return c;
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_ctz|\\.CLZ" "optimized" } } */
\ No newline at end of file
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 0fde07e626f5..92db9c72ee47 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -2303,6 +2303,38 @@ build_cltz_expr (tree src, bool leading, bool 
define_at_zero)
   return call;
 }
 
+/* Returns true if STMT is equivalent to x << 1.  */
+
+static bool
+is_lshift_by_1 (gassign *stmt)
+{
+  if (gimple_assign_rhs_code (stmt) == LSHIFT_EXPR
+  && integer_onep (gimple_assign_rhs2 (stmt)))
+return true;
+  if (gimple_assign_rhs_code (stmt) == MULT_EXPR
+  && tree_fits_shwi_p (gimple_assign_rhs2 (stmt))
+  && tree_to_shwi (gimple_assign_rhs2 (stmt)) == 2)
+return true;
+  return false;
+}
+
+/* Returns true if STMT is equivalent to x >> 1.  */
+
+static bool
+is_rshift_by_1 (gassign *stmt)
+{
+  if (!TYPE_UNSIGNED (TREE_TYPE (gimple_assign_lhs (stmt
+return false;
+  if (gimple_assign_rhs_code (stmt) == RSHIFT_EXPR
+  && integer_onep (gimple_assign_rhs2 (stmt)))
+return true;
+  if (gimple_assign_rhs_code (stmt) == TRUNC_DIV_EXPR
+  && tree_fits_shwi_p (gimple_assign_rhs2 (stmt))
+  && tree_to_shwi (gimple_assign_rhs2 (stmt)) == 2)
+return true;
+  return false;
+}
+
 /* See comment below for number_of_iterations_bitcount.
For c[lt]z, we have:
 
@@ -2400,14 +2432,12 @@ number_of_iterations_cltz (loop_p loop, edge exit,
 
   /* Make sure iv_2_stmt is a logical shift by one stmt:
  iv_2 = iv_1 {<<|>>} 1  */
-  if (!is_gimple_assign (iv_2_stmt)
-  || (gimple_assign_rhs_code (iv_2_stmt) != 

[gcc r15-379] [prange] Default unimplemented prange operators to false.

2024-05-11 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:18c93c65a9fbaaf3762198e78fb3c24b9b6fd9fc

commit r15-379-g18c93c65a9fbaaf3762198e78fb3c24b9b6fd9fc
Author: Aldy Hernandez 
Date:   Fri May 10 18:55:34 2024 +0200

[prange] Default unimplemented prange operators to false.

The canonical way to indicate that a range operator is unsupported is
to return false, which has the sematic meaning of VARYING.  This patch
cleans up a few default virtuals that were trying harder to set
VARYING manually.

gcc/ChangeLog:

* range-op-ptr.cc (range_operator::fold_range): Return false.

Diff:
---
 gcc/range-op-ptr.cc | 55 +++--
 1 file changed, 15 insertions(+), 40 deletions(-)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 466edc6bf746..65cca65103af 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -62,63 +62,38 @@ range_operator::pointers_handled_p (range_op_dispatch_type 
ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const prange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const prange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const prange ,
-   const irange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const prange &, const irange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (irange , tree type,
-   const prange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (irange &, tree, const prange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const irange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const irange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (irange , tree type,
-   const prange ,
-   const irange ,
-   relation_trio trio) const
+range_operator::fold_range (irange &, tree, const prange &, const irange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool


[gcc r15-378] [prange] Do not trap by default on range dispatch mismatches.

2024-05-11 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:45ef24f2702dac4f8707ca682ed364019ee90c44

commit r15-378-g45ef24f2702dac4f8707ca682ed364019ee90c44
Author: Aldy Hernandez 
Date:   Fri May 10 23:21:29 2024 +0200

[prange] Do not trap by default on range dispatch mismatches.

The trap in the range-op dispatch code is really an internal debugging
aid, and only a temporary one for a few weeks while the dust settles.
This patch turns it off by default, allowing problematic passes to
turn it on for analysis.

gcc/ChangeLog:

* range-op.cc (TRAP_ON_UNHANDLED_POINTER_OPERATORS): New
(range_op_handler::fold_range): Use it.
(range_op_handler::op1_range): Same.
(range_op_handler::op2_range): Same.
(range_op_handler::lhs_op1_relation): Same.
(range_op_handler::lhs_op2_relation): Same.
(range_op_handler::op1_op2_relation): Same.

Diff:
---
 gcc/range-op.cc | 23 +--
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index a134af68141e..6a410ff656c5 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -49,6 +49,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-ccp.h"
 #include "range-op-mixed.h"
 
+// Set to 1 to trap on range-op entries that cannot handle the pointer
+// combination being requested.  This is a temporary sanity check to
+// aid in debugging, and will be removed later in the release cycle.
+#define TRAP_ON_UNHANDLED_POINTER_OPERATORS 0
+
 // Instantiate the operators which apply to multiple types here.
 
 operator_equal op_equal;
@@ -233,7 +238,8 @@ range_op_handler::fold_range (vrange , tree type,
 #if CHECKING_P
   if (!lh.undefined_p () && !rh.undefined_p ())
 gcc_assert (m_operator->operand_check_p (type, lh.type (), rh.type ()));
-  if (has_pointer_operand_p (r, lh, rh)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lh, rh)
   && !m_operator->pointers_handled_p (DISPATCH_FOLD_RANGE,
  dispatch_kind (r, lh, rh)))
 discriminator_fail (r, lh, rh);
@@ -299,7 +305,8 @@ range_op_handler::op1_range (vrange , tree type,
 #if CHECKING_P
   if (!op2.undefined_p ())
 gcc_assert (m_operator->operand_check_p (lhs.type (), type, op2.type ()));
-  if (has_pointer_operand_p (r, lhs, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lhs, op2)
   && !m_operator->pointers_handled_p (DISPATCH_OP1_RANGE,
  dispatch_kind (r, lhs, op2)))
 discriminator_fail (r, lhs, op2);
@@ -353,7 +360,8 @@ range_op_handler::op2_range (vrange , tree type,
 #if CHECKING_P
   if (!op1.undefined_p ())
 gcc_assert (m_operator->operand_check_p (lhs.type (), op1.type (), type));
-  if (has_pointer_operand_p (r, lhs, op1)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lhs, op1)
   && !m_operator->pointers_handled_p (DISPATCH_OP2_RANGE,
  dispatch_kind (r, lhs, op1)))
 discriminator_fail (r, lhs, op1);
@@ -395,7 +403,8 @@ range_op_handler::lhs_op1_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_LHS_OP1_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);
@@ -442,7 +451,8 @@ range_op_handler::lhs_op2_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_LHS_OP2_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);
@@ -475,7 +485,8 @@ range_op_handler::op1_op2_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_OP1_OP2_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);


[gcc(refs/users/mikael/heads/pr99798_v66)] fortran: Fix leaked symbol

2024-05-11 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:4b2e3dff5615a16532f42459fc5d0400c6d61f05

commit 4b2e3dff5615a16532f42459fc5d0400c6d61f05
Author: Mikael Morin 
Date:   Fri May 10 11:17:41 2024 +0200

fortran: Fix leaked symbol

For a symbol we create, this adds a reference to a it in a namespace, so
that its memory is not leaked.  A hidden name is used to avoid polluting
the namespace.

gcc/fortran/ChangeLog:

* decl.cc (get_proc_name): Reference the interface symbol in the
namespace under a hidden name.

Diff:
---
 gcc/fortran/decl.cc | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index b8308aeee550..ce0fb6bae594 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -1335,6 +1335,10 @@ get_proc_name (const char *name, gfc_symbol **result, 
bool module_fcn_entry)
   /* Create a partially populated interface symbol to carry the
 characteristics of the procedure and the result.  */
   sym->tlink = gfc_new_symbol (name, sym->ns);
+  gfc_symtree *s = gfc_get_unique_symtree (sym->ns);
+  s->n.sym = sym->tlink;
+  s->n.sym->refs++;
+
   gfc_add_type (sym->tlink, &(sym->ts), _current_locus);
   gfc_copy_attr (>tlink->attr, >attr, NULL);
   if (sym->attr.dimension)


[gcc(refs/users/mikael/heads/pr99798_v66)] fortran: Assume there is no cyclic reference with submodule symbols [PR99798]

2024-05-11 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:934742d5d2706d3dc3df1dad7cd7ad1cfd6d6370

commit 934742d5d2706d3dc3df1dad7cd7ad1cfd6d6370
Author: Mikael Morin 
Date:   Fri May 10 11:14:48 2024 +0200

fortran: Assume there is no cyclic reference with submodule symbols 
[PR99798]

This prevents a premature release of memory with procedure symbols from
submodules, causing random compiler crashes.

The problem is a fragile detection of cyclic references, which can match
with procedures host-associated from a module in submodules, in cases where 
it
shouldn't.  The formal namespace is released, and with it the dummy 
arguments
symbols of the procedure.  But there is no cyclic reference, so the 
procedure
symbol itself is not released and remains, with pointers to its dummy 
arguments
now dangling.

The fix adds a condition to avoid the case, and refactors to a new 
predicate by
the way.

PR fortran/99798

gcc/fortran/ChangeLog:

* symbol.cc (gfc_release_symbol): Move the condition guarding
the cyclic references handling...
(cyclic_reference_break_needed): ... here as a new predicate.  Add
a condition preventing any premature release with submodule symbols.

gcc/testsuite/ChangeLog:

* gfortran.dg/submodule_33.f08: New test.

Diff:
---
 gcc/fortran/symbol.cc  | 54 --
 gcc/testsuite/gfortran.dg/submodule_33.f08 | 20 +++
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 8f7deac1d1ee..0a1646def678 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -3179,6 +3179,57 @@ gfc_free_symbol (gfc_symbol *)
 }
 
 
+/* Returns true if the symbol SYM has, through its FORMAL_NS field, a reference
+   to itself which should be eliminated for the symbol memory to be released
+   via normal reference counting.
+
+   The implementation is crucial as it controls the proper release of symbols,
+   especially (contained) procedure symbols, which can represent a lot of 
memory
+   through the namespace of their body.
+
+   We try to avoid freeing too much memory (causing dangling pointers), to not
+   leak too much (wasting memory), and to avoid expensive walks of the symbol
+   tree (which would be the correct way to check for a cycle).  */
+
+bool
+cyclic_reference_break_needed (gfc_symbol *sym)
+{
+  /* Normal symbols don't reference themselves.  */
+  if (sym->formal_ns == nullptr)
+return false;
+
+  /* Procedures at the root of the file do have a self reference, but they 
don't
+ have a reference in a parent namespace preventing the release of the
+ procedure namespace, so they can use the normal reference counting.  */
+  if (sym->formal_ns == sym->ns)
+return false;
+
+  /* If sym->refs == 1, we can use normal reference counting.  If sym->refs > 
2,
+ the symbol won't be freed anyway, with or without cyclic reference.  */
+  if (sym->refs != 2)
+return false;
+
+  /* Procedure symbols host-associated from a module in submodules are special,
+ because the namespace of the procedure block in the submodule is different
+ from the FORMAL_NS namespace generated by host-association.  So there are
+ two different namespaces representing the same procedure namespace.  As
+ FORMAL_NS comes from host-association, which only imports symbols visible
+ from the outside (dummy arguments basically), we can assume there is no
+ self reference through FORMAL_NS in that case.  */
+  if (sym->attr.host_assoc && sym->attr.used_in_submodule)
+return false;
+
+  /* We can assume that contained procedures have cyclic references, because
+ the symbol of the procedure itself is accessible in the procedure body
+ namespace.  So we assume that symbols with a formal namespace different
+ from the declaration namespace and two references, one of which is about
+ to be removed, are procedures with just the self reference left.  At this
+ point, the symbol SYM matches that pattern, so we return true here to
+ permit the release of SYM.  */
+  return true;
+}
+
+
 /* Decrease the reference counter and free memory when we reach zero.
Returns true if the symbol has been freed, false otherwise.  */
 
@@ -3188,8 +3239,7 @@ gfc_release_symbol (gfc_symbol *)
   if (sym == NULL)
 return false;
 
-  if (sym->formal_ns != NULL && sym->refs == 2 && sym->formal_ns != sym->ns
-  && (!sym->attr.entry || !sym->module))
+  if (cyclic_reference_break_needed (sym))
 {
   /* As formal_ns contains a reference to sym, delete formal_ns just
 before the deletion of sym.  */
diff --git a/gcc/testsuite/gfortran.dg/submodule_33.f08 
b/gcc/testsuite/gfortran.dg/submodule_33.f08
new file mode 100644
index ..b61d750def16
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/submodule_33.f08
@@ -0,0 +1,20 @@
+! { 

[gcc] Created branch 'mikael/heads/pr99798_v66' in namespace 'refs/users'

2024-05-11 Thread Mikael Morin via Gcc-cvs
The branch 'mikael/heads/pr99798_v66' was created in namespace 'refs/users' 
pointing to:

 4b2e3dff5615... fortran: Fix leaked symbol