Fail of x86_64 AMX-COMPLEX insns (Intel disassembly)
[binutils-gdb.git] / gas / read.c
index 559fd05a8dbf7fa2ea7a7e47dc1a1727d4631520..ac39fc9582ebb1cdfef70a1181355869b0671ac8 100644 (file)
@@ -1,5 +1,5 @@
 /* read.c - read a source file -
-   Copyright (C) 1986-2022 Free Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -38,7 +38,9 @@
 #include "obstack.h"
 #include "ecoff.h"
 #include "dw2gencfi.h"
+#include "codeview.h"
 #include "wchar.h"
+#include "filenames.h"
 
 #include <limits.h>
 
@@ -172,10 +174,10 @@ int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
 const char **include_dirs;
 
 /* How many are in the table.  */
-int include_dir_count;
+size_t include_dir_count;
 
 /* Length of longest in table.  */
-int include_dir_maxlen = 1;
+size_t include_dir_maxlen;
 
 #ifndef WORKING_DOT_WORD
 struct broken_word *broken_words;
@@ -202,8 +204,17 @@ symbolS *mri_common_symbol;
    may be needed.  */
 static int mri_pending_align;
 
+/* Record the current function so that we can issue an error message for
+   misplaced .func,.endfunc, and also so that .endfunc needs no
+   arguments.  */
+static char *current_name;
+static char *current_label;
+
 #ifndef NO_LISTING
 #ifdef OBJ_ELF
+static int dwarf_file;
+static int dwarf_line;
+
 /* This variable is set to be non-zero if the next string we see might
    be the name of the source file in DWARF debugging information.  See
    the comment in emit_expr for the format we look for.  */
@@ -273,11 +284,42 @@ read_begin (void)
 
   if (flag_mri)
     lex_type['?'] = 3;
+  stabs_begin ();
+
+#ifndef WORKING_DOT_WORD
+  broken_words = NULL;
+  new_broken_words = 0;
+#endif
+
+  abs_section_offset = 0;
+
+  line_label = NULL;
+  mri_common_symbol = NULL;
+  mri_pending_align = 0;
+
+  current_name = NULL;
+  current_label = NULL;
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+  dwarf_file = 0;
+  dwarf_line = -1;
+  dwarf_file_string = 0;
+#endif
+#endif
+
+#ifdef HANDLE_BUNDLE
+  bundle_align_p2 = 0;
+  bundle_lock_frag = NULL;
+  bundle_lock_frchain = NULL;
+  bundle_lock_depth = 0;
+#endif
 }
 
 void
 read_end (void)
 {
+  stabs_end ();
   poend ();
   _obstack_free (&cond_obstack, NULL);
 }
@@ -513,7 +555,7 @@ get_absolute_expression (void)
   return get_absolute_expr (&exp);
 }
 
-static int pop_override_ok = 0;
+static int pop_override_ok;
 static const char *pop_table_name;
 
 void
@@ -550,6 +592,7 @@ pobegin (void)
 
   /* Do the target-specific pseudo ops.  */
   pop_table_name = "md";
+  pop_override_ok = 0;
   md_pop_insert ();
 
   /* Now object specific.  Skip any that were in the target table.  */
@@ -563,7 +606,6 @@ pobegin (void)
 
   /* Now CFI ones.  */
   pop_table_name = "cfi";
-  pop_override_ok = 1;
   cfi_pop_insert ();
 }
 
@@ -834,9 +876,8 @@ read_a_source_file (const char *name)
 #ifndef NO_LISTING
       /* In order to avoid listing macro expansion lines with labels
         multiple times, keep track of which line was last issued.  */
-      static char *last_eol;
+      char *last_eol = NULL;
 
-      last_eol = NULL;
 #endif
       while (input_line_pointer < buffer_limit)
        {
@@ -867,7 +908,10 @@ read_a_source_file (const char *name)
                  /* Find the end of the current expanded macro line.  */
                  s = find_end_of_line (input_line_pointer, flag_m68k_mri);
 
-                 if (s != last_eol)
+                 if (s != last_eol
+                     && !startswith (input_line_pointer,
+                                     !flag_m68k_mri ? " .linefile "
+                                                    : " linefile "))
                    {
                      char *copy;
                      size_t len;
@@ -1572,7 +1616,7 @@ static void
 s_altmacro (int on)
 {
   demand_empty_rest_of_line ();
-  macro_set_alternate (on);
+  flag_macro_alternate = on;
 }
 
 /* Read a symbol name from input_line_pointer.
@@ -1629,7 +1673,10 @@ read_symbol_name (void)
       /* Since quoted symbol names can contain non-ASCII characters,
         check the string and warn if it cannot be recognised by the
         current character set.  */
-      if (mbstowcs (NULL, name, len) == (size_t) -1)
+      /* PR 29447: mbstowcs ignores the third (length) parameter when
+        the first (destination) parameter is NULL.  For clarity sake
+        therefore we pass 0 rather than 'len' as the third parameter.  */
+      if (mbstowcs (NULL, name, 0) == (size_t) -1)
        as_warn (_("symbol name not recognised in the current locale"));
     }
   else if (is_name_beginner (c) || (input_from_string && c == FAKE_LABEL_CHAR))
@@ -2040,18 +2087,22 @@ s_linefile (int ignore ATTRIBUTE_UNUSED)
 
       if (file || flags)
        {
-         linenum--;
+         demand_empty_rest_of_line ();
+
+         /* read_a_source_file() will bump the line number only if the line
+            is terminated by '\n'.  */
+         if (input_line_pointer[-1] == '\n')
+           linenum--;
+
          new_logical_line_flags (file, linenum, flags);
 #ifdef LISTING
          if (listing)
            listing_source_line (linenum);
 #endif
+         return;
        }
     }
-  if (file || flags)
-    demand_empty_rest_of_line ();
-  else
-    ignore_rest_of_line ();
+  ignore_rest_of_line ();
 }
 
 /* Handle the .end pseudo-op.  Actually, the real work is done in
@@ -2188,22 +2239,32 @@ s_fill (int ignore ATTRIBUTE_UNUSED)
        as_warn (_("repeat < 0; .fill ignored"));
       size = 0;
     }
-
-  if (size && !need_pass_2)
+  else if (size && !need_pass_2)
     {
-      if (now_seg == absolute_section)
+      if (now_seg == absolute_section && rep_exp.X_op != O_constant)
+       {
+         as_bad (_("non-constant fill count for absolute section"));
+         size = 0;
+       }
+      else if (now_seg == absolute_section && fill && rep_exp.X_add_number != 0)
        {
-         if (rep_exp.X_op != O_constant)
-           as_bad (_("non-constant fill count for absolute section"));
-         else if (fill && rep_exp.X_add_number != 0)
-           as_bad (_("attempt to fill absolute section with non-zero value"));
-         abs_section_offset += rep_exp.X_add_number * size;
+         as_bad (_("attempt to fill absolute section with non-zero value"));
+         size = 0;
        }
       else if (fill
               && (rep_exp.X_op != O_constant || rep_exp.X_add_number != 0)
               && in_bss ())
-       as_bad (_("attempt to fill section `%s' with non-zero value"),
-               segment_name (now_seg));
+       {
+         as_bad (_("attempt to fill section `%s' with non-zero value"),
+                 segment_name (now_seg));
+         size = 0;
+       }
+    }
+
+  if (size && !need_pass_2)
+    {
+      if (now_seg == absolute_section)
+       abs_section_offset += rep_exp.X_add_number * size;
 
       if (rep_exp.X_op == O_constant)
        {
@@ -2640,13 +2701,8 @@ void
 s_macro (int ignore ATTRIBUTE_UNUSED)
 {
   char *eol;
-  const char * file;
-  unsigned int line;
   sb s;
-  const char *err;
-  const char *name;
-
-  file = as_where (&line);
+  macro_entry *macro;
 
   eol = find_end_of_line (input_line_pointer, 0);
   sb_build (&s, eol - input_line_pointer);
@@ -2657,19 +2713,18 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
     {
       sb label;
       size_t len;
+      const char *name;
 
       name = S_GET_NAME (line_label);
       len = strlen (name);
       sb_build (&label, len);
       sb_add_buffer (&label, name, len);
-      err = define_macro (0, &s, &label, get_macro_line_sb, file, line, &name);
+      macro = define_macro (&s, &label, get_macro_line_sb);
       sb_kill (&label);
     }
   else
-    err = define_macro (0, &s, NULL, get_macro_line_sb, file, line, &name);
-  if (err != NULL)
-    as_bad_where (file, line, err, name);
-  else
+    macro = define_macro (&s, NULL, get_macro_line_sb);
+  if (macro != NULL)
     {
       if (line_label != NULL)
        {
@@ -2679,14 +2734,16 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
        }
 
       if (((NO_PSEUDO_DOT || flag_m68k_mri)
-          && str_hash_find (po_hash, name) != NULL)
+          && str_hash_find (po_hash, macro->name) != NULL)
          || (!flag_m68k_mri
-             && *name == '.'
-             && str_hash_find (po_hash, name + 1) != NULL))
-       as_warn_where (file,
-                line,
-                _("attempt to redefine pseudo-op `%s' ignored"),
-                name);
+             && macro->name[0] == '.'
+             && str_hash_find (po_hash, macro->name + 1) != NULL))
+       {
+         as_warn_where (macro->file, macro->line,
+                        _("attempt to redefine pseudo-op `%s' ignored"),
+                        macro->name);
+         str_hash_delete (macro_hash, macro->name);
+       }
     }
 
   sb_kill (&s);
@@ -2727,7 +2784,6 @@ s_mri (int ignore ATTRIBUTE_UNUSED)
 #ifdef TC_M68K
       flag_m68k_mri = 1;
 #endif
-      macro_mri_mode (1);
     }
   else
     {
@@ -2735,7 +2791,6 @@ s_mri (int ignore ATTRIBUTE_UNUSED)
 #ifdef TC_M68K
       flag_m68k_mri = 0;
 #endif
-      macro_mri_mode (0);
     }
 
   /* Operator precedence changes in m68k MRI mode, so we need to
@@ -3020,6 +3075,7 @@ do_repeat (size_t count, const char *start, const char *end,
   if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
     {
       as_bad (_("%s without %s"), start, end);
+      sb_kill (&one);
       return;
     }
 
@@ -3308,27 +3364,37 @@ s_space (int mult)
 
       if (exp.X_op == O_constant)
        {
-         offsetT repeat;
+         addressT repeat = exp.X_add_number;
+         addressT total;
 
-         repeat = exp.X_add_number;
-         if (mult)
-           repeat *= mult;
-         bytes = repeat;
-         if (repeat <= 0)
+         bytes = 0;
+         if ((offsetT) repeat < 0)
+           {
+             as_warn (_(".space repeat count is negative, ignored"));
+             goto getout;
+           }
+         if (repeat == 0)
            {
              if (!flag_mri)
                as_warn (_(".space repeat count is zero, ignored"));
-             else if (repeat < 0)
-               as_warn (_(".space repeat count is negative, ignored"));
              goto getout;
            }
+         if ((unsigned int) mult <= 1)
+           total = repeat;
+         else if (gas_mul_overflow (repeat, mult, &total)
+                  || (offsetT) total < 0)
+           {
+             as_warn (_(".space repeat count overflow, ignored"));
+             goto getout;
+           }
+         bytes = total;
 
          /* If we are in the absolute section, just bump the offset.  */
          if (now_seg == absolute_section)
            {
              if (val.X_op != O_constant || val.X_add_number != 0)
                as_warn (_("ignoring fill value in absolute section"));
-             abs_section_offset += repeat;
+             abs_section_offset += total;
              goto getout;
            }
 
@@ -3338,13 +3404,13 @@ s_space (int mult)
          if (mri_common_symbol != NULL)
            {
              S_SET_VALUE (mri_common_symbol,
-                          S_GET_VALUE (mri_common_symbol) + repeat);
+                          S_GET_VALUE (mri_common_symbol) + total);
              goto getout;
            }
 
          if (!need_pass_2)
            p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
-                         (offsetT) repeat, (char *) 0);
+                         (offsetT) total, (char *) 0);
        }
       else
        {
@@ -4145,7 +4211,7 @@ s_reloc (int ignore ATTRIBUTE_UNUSED)
   int c;
   struct reloc_list *reloc;
   struct _bfd_rel { const char * name; bfd_reloc_code_real_type code; };
-  static struct _bfd_rel bfd_relocs[] =
+  static const struct _bfd_rel bfd_relocs[] =
   {
     { "NONE", BFD_RELOC_NONE },
     { "8",  BFD_RELOC_8 },
@@ -4295,62 +4361,54 @@ emit_expr_with_reloc (expressionS *exp,
   /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
      appear as a four byte positive constant in the .line section,
      followed by a 2 byte 0xffff.  Look for that case here.  */
-  {
-    static int dwarf_line = -1;
-
-    if (strcmp (segment_name (now_seg), ".line") != 0)
-      dwarf_line = -1;
-    else if (dwarf_line >= 0
-            && nbytes == 2
-            && exp->X_op == O_constant
-            && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
-      listing_source_line ((unsigned int) dwarf_line);
-    else if (nbytes == 4
-            && exp->X_op == O_constant
-            && exp->X_add_number >= 0)
-      dwarf_line = exp->X_add_number;
-    else
-      dwarf_line = -1;
-  }
+  if (strcmp (segment_name (now_seg), ".line") != 0)
+    dwarf_line = -1;
+  else if (dwarf_line >= 0
+          && nbytes == 2
+          && exp->X_op == O_constant
+          && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
+    listing_source_line ((unsigned int) dwarf_line);
+  else if (nbytes == 4
+          && exp->X_op == O_constant
+          && exp->X_add_number >= 0)
+    dwarf_line = exp->X_add_number;
+  else
+    dwarf_line = -1;
 
   /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
      appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
      AT_sibling (0x12) followed by a four byte address of the sibling
      followed by a 2 byte AT_name (0x38) followed by the name of the
      file.  We look for that case here.  */
-  {
-    static int dwarf_file = 0;
-
-    if (strcmp (segment_name (now_seg), ".debug") != 0)
-      dwarf_file = 0;
-    else if (dwarf_file == 0
-            && nbytes == 2
-            && exp->X_op == O_constant
-            && exp->X_add_number == 0x11)
-      dwarf_file = 1;
-    else if (dwarf_file == 1
-            && nbytes == 2
-            && exp->X_op == O_constant
-            && exp->X_add_number == 0x12)
-      dwarf_file = 2;
-    else if (dwarf_file == 2
-            && nbytes == 4)
-      dwarf_file = 3;
-    else if (dwarf_file == 3
-            && nbytes == 2
-            && exp->X_op == O_constant
-            && exp->X_add_number == 0x38)
-      dwarf_file = 4;
-    else
-      dwarf_file = 0;
-
-    /* The variable dwarf_file_string tells stringer that the string
-       may be the name of the source file.  */
-    if (dwarf_file == 4)
-      dwarf_file_string = 1;
-    else
-      dwarf_file_string = 0;
-  }
+  if (strcmp (segment_name (now_seg), ".debug") != 0)
+    dwarf_file = 0;
+  else if (dwarf_file == 0
+          && nbytes == 2
+          && exp->X_op == O_constant
+          && exp->X_add_number == 0x11)
+    dwarf_file = 1;
+  else if (dwarf_file == 1
+          && nbytes == 2
+          && exp->X_op == O_constant
+          && exp->X_add_number == 0x12)
+    dwarf_file = 2;
+  else if (dwarf_file == 2
+          && nbytes == 4)
+    dwarf_file = 3;
+  else if (dwarf_file == 3
+          && nbytes == 2
+          && exp->X_op == O_constant
+          && exp->X_add_number == 0x38)
+    dwarf_file = 4;
+  else
+    dwarf_file = 0;
+
+  /* The variable dwarf_file_string tells stringer that the string
+     may be the name of the source file.  */
+  if (dwarf_file == 4)
+    dwarf_file_string = 1;
+  else
+    dwarf_file_string = 0;
 #endif
 #endif
 
@@ -4495,14 +4553,9 @@ emit_expr_with_reloc (expressionS *exp,
       use = get & unmask;
       if ((get & mask) != 0 && (-get & mask) != 0)
        {
-         char get_buf[128];
-         char use_buf[128];
-
-         /* These buffers help to ease the translation of the warning message.  */
-         sprintf_vma (get_buf, get);
-         sprintf_vma (use_buf, use);
          /* Leading bits contain both 0s & 1s.  */
-         as_warn (_("value 0x%s truncated to 0x%s"), get_buf, use_buf);
+         as_warn (_("value 0x%" PRIx64 " truncated to 0x%" PRIx64),
+                  (uint64_t) get, (uint64_t) use);
        }
       /* Put bytes in right order.  */
       md_number_to_chars (p, use, (int) nbytes);
@@ -5721,6 +5774,30 @@ equals (char *sym_name, int reassign)
     }
 }
 
+/* Open FILENAME, first trying the unadorned file name, then if that
+   fails and the file name is not an absolute path, attempt to open
+   the file in current -I include paths.  PATH is a preallocated
+   buffer which will be set to the file opened, or FILENAME if no file
+   is found.  */
+
+FILE *
+search_and_open (const char *filename, char *path)
+{
+  FILE *f = fopen (filename, FOPEN_RB);
+  if (f == NULL && !IS_ABSOLUTE_PATH (filename))
+    {
+      for (size_t i = 0; i < include_dir_count; i++)
+       {
+         sprintf (path, "%s/%s", include_dirs[i], filename);
+         f = fopen (path, FOPEN_RB);
+         if (f != NULL)
+           return f;
+       }
+    }
+  strcpy (path, filename);
+  return f;
+}
+
 /* .incbin -- include a file verbatim at the current location.  */
 
 void
@@ -5772,30 +5849,12 @@ s_incbin (int x ATTRIBUTE_UNUSED)
 
   demand_empty_rest_of_line ();
 
-  /* Try opening absolute path first, then try include dirs.  */
-  binfile = fopen (filename, FOPEN_RB);
-  if (binfile == NULL)
-    {
-      int i;
+  path = XNEWVEC (char, len + include_dir_maxlen + 2);
+  binfile = search_and_open (filename, path);
 
-      path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
-
-      for (i = 0; i < include_dir_count; i++)
-       {
-         sprintf (path, "%s/%s", include_dirs[i], filename);
-
-         binfile = fopen (path, FOPEN_RB);
-         if (binfile != NULL)
-           break;
-       }
-
-      if (binfile == NULL)
-       as_bad (_("file not found: %s"), filename);
-    }
+  if (binfile == NULL)
+    as_bad (_("file not found: %s"), filename);
   else
-    path = xstrdup (filename);
-
-  if (binfile)
     {
       long   file_len;
       struct stat filestat;
@@ -5889,48 +5948,33 @@ s_include (int arg ATTRIBUTE_UNUSED)
     }
 
   demand_empty_rest_of_line ();
-  path = notes_alloc ((size_t) i + include_dir_maxlen + 5);
 
-  for (i = 0; i < include_dir_count; i++)
-    {
-      strcpy (path, include_dirs[i]);
-      strcat (path, "/");
-      strcat (path, filename);
-      if (0 != (try_file = fopen (path, FOPEN_RT)))
-       {
-         fclose (try_file);
-         goto gotit;
-       }
-    }
+  path = notes_alloc (i + include_dir_maxlen + 2);
+  try_file = search_and_open (filename, path);
+  if (try_file)
+    fclose (try_file);
 
-  notes_free (path);
-  path = filename;
- gotit:
   register_dependency (path);
   input_scrub_insert_file (path);
 }
 
 void
-add_include_dir (char *path)
+init_include_dir (void)
 {
-  int i;
-
-  if (include_dir_count == 0)
-    {
-      include_dirs = XNEWVEC (const char *, 2);
-      include_dirs[0] = ".";   /* Current dir.  */
-      include_dir_count = 2;
-    }
-  else
-    {
-      include_dir_count++;
-      include_dirs = XRESIZEVEC (const char *, include_dirs,
-                                include_dir_count);
-    }
+  include_dirs = XNEWVEC (const char *, 1);
+  include_dirs[0] = ".";       /* Current dir.  */
+  include_dir_count = 1;
+  include_dir_maxlen = 1;
+}
 
+void
+add_include_dir (char *path)
+{
+  include_dir_count++;
+  include_dirs = XRESIZEVEC (const char *, include_dirs, include_dir_count);
   include_dirs[include_dir_count - 1] = path;  /* New one.  */
 
-  i = strlen (path);
+  size_t i = strlen (path);
   if (i > include_dir_maxlen)
     include_dir_maxlen = i;
 }
@@ -5967,6 +6011,9 @@ generate_lineno_debug (void)
         support that is required (calling dwarf2_emit_insn), we
         let dwarf2dbg.c call as_where on its own.  */
       break;
+    case DEBUG_CODEVIEW:
+      codeview_generate_asm_lineno ();
+      break;
     }
 }
 
@@ -5985,12 +6032,6 @@ s_func (int end_p)
 static void
 do_s_func (int end_p, const char *default_prefix)
 {
-  /* Record the current function so that we can issue an error message for
-     misplaced .func,.endfunc, and also so that .endfunc needs no
-     arguments.  */
-  static char *current_name;
-  static char *current_label;
-
   if (end_p)
     {
       if (current_name == NULL)
@@ -6235,7 +6276,7 @@ find_end_of_line (char *s, int mri_string)
   return _find_end_of_line (s, mri_string, 0, 0);
 }
 
-static char *saved_ilp = NULL;
+static char *saved_ilp;
 static char *saved_limit;
 
 /* Use BUF as a temporary input pointer for calling other functions in this