* dw2gencfi.c (struct cfi_escape_data): New.
authorRichard Henderson <rth@redhat.com>
Wed, 11 Jun 2003 23:16:58 +0000 (23:16 +0000)
committerRichard Henderson <rth@redhat.com>
Wed, 11 Jun 2003 23:16:58 +0000 (23:16 +0000)
        (cfi_add_CFA_nop): Remove.
        (CFI_escape, dot_cfi_escape): New.
        (dot_cfi): Remove nop.
        (cfi_pseudo_table): Remove nop; add escape.
        (output_cfi_insn): Likewise.
        (select_cie_for_fde): Stop on escape.
        * dw2gencfi.h (cfi_add_CFA_nop): Remove.
        * read.c, read.h (do_parse_cons_expression): New.
        * doc/as.texinfo (.cfi_escape): New.

        * gas/cfi/cfi-common-3.[ds]: New.
        * gas/cfi/cfi.exp: Run it.

gas/ChangeLog
gas/doc/as.texinfo
gas/dw2gencfi.c
gas/dw2gencfi.h
gas/read.c
gas/read.h
gas/testsuite/ChangeLog
gas/testsuite/gas/cfi/cfi-common-3.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-common-3.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi.exp

index 38430a3eceaac7943017afedb9fc0abb5a7e89a6..9df96ef3bb948fd2d247c30ddd69a7d049ae3b49 100644 (file)
@@ -1,3 +1,16 @@
+2003-06-11  Richard Henderson  <rth@redhat.com>
+
+       * dw2gencfi.c (struct cfi_escape_data): New.
+       (cfi_add_CFA_nop): Remove.
+       (CFI_escape, dot_cfi_escape): New.
+       (dot_cfi): Remove nop.
+       (cfi_pseudo_table): Remove nop; add escape.
+       (output_cfi_insn): Likewise.
+       (select_cie_for_fde): Stop on escape.
+       * dw2gencfi.h (cfi_add_CFA_nop): Remove.
+       * read.c, read.h (do_parse_cons_expression): New.
+       * doc/as.texinfo (.cfi_escape): New.
+
 2003-06-11  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
 
        * config/tc-mips.c (s_cpsetup): Use mips_frame_reg instead of SP.
index d37198a10a6e5d37989b3d0a38a686842bd0d28c..3e608d48e5af9f812a9b63174486a6a31e7d7adf 100644 (file)
@@ -3691,13 +3691,7 @@ Some machine configurations provide additional directives.
 * Byte::                        @code{.byte @var{expressions}}
 * Comm::                        @code{.comm @var{symbol} , @var{length} }
 
-* CFI directives::             @code{.cfi_startproc}
-                               @code{.cfi_endproc}
-                               @code{.cfi_def_cfa @var{register}, @var{offset}}
-                               @code{.cfi_def_cfa_register @var{register}}
-                               @code{.cfi_def_cfa_offset @var{offset}}
-                               @code{.cfi_adjust_cfa_offset @var{offset}}
-                               @code{.cfi_offset @var{register}, @var{offset}}
+* CFI directives::             @code{.cfi_startproc}, @code{.cfi_endproc}, etc.
 
 * Data::                        @code{.data @var{subsection}}
 @ifset COFF
@@ -4020,8 +4014,10 @@ using the known displacement of the CFA register from the CFA.
 This is often easier to use, because the number will match the
 code it's annotating.
 
-@node Comm
-@section @code{.comm @var{symbol} , @var{length} }
+@section @code{.cfi_escape} @var{expression}[, @dots{}]
+Allows the user to add arbitrary bytes to the unwind info.  One
+might use this to add OS-specific CFI opcodes, or generic CFI
+opcodes that GAS does not yet support.
 
 @cindex @code{comm} directive
 @cindex symbol, common
index ccfb1103a16bdf4705953c8c1a6cc5a5059e0c5a..0e118e15d3969d107c7c4d158c7b8e090f92b52f 100644 (file)
@@ -68,6 +68,11 @@ struct cfi_insn_data
       symbolS *lab1;
       symbolS *lab2;
     } ll;
+
+    struct cfi_escape_data {
+      struct cfi_escape_data *next;
+      expressionS exp;
+    } *esc;
   } u;
 };
 
@@ -330,16 +335,11 @@ cfi_add_CFA_restore_state (void)
     }
 }
 
-void
-cfi_add_CFA_nop (void)
-{
-  cfi_add_CFA_insn (DW_CFA_nop);
-}
-
 \f
 /* Parse CFI assembler directives.  */
 
 static void dot_cfi (int);
+static void dot_cfi_escape (int);
 static void dot_cfi_startproc (int);
 static void dot_cfi_endproc (int);
 
@@ -347,6 +347,7 @@ static void dot_cfi_endproc (int);
 #define CFI_adjust_cfa_offset  0x100
 #define CFI_return_column      0x101
 #define CFI_rel_offset         0x102
+#define CFI_escape             0x103
 
 const pseudo_typeS cfi_pseudo_table[] =
   {
@@ -365,7 +366,7 @@ const pseudo_typeS cfi_pseudo_table[] =
     { "cfi_same_value", dot_cfi, DW_CFA_same_value },
     { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
     { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
-    { "cfi_nop", dot_cfi, DW_CFA_nop },
+    { "cfi_escape", dot_cfi_escape, 0 },
     { NULL, NULL, 0 }
   };
 
@@ -520,10 +521,6 @@ dot_cfi (int arg)
       cfi_add_CFA_restore_state ();
       break;
 
-    case DW_CFA_nop:
-      cfi_add_CFA_nop ();
-      break;
-
     default:
       abort ();
     }
@@ -531,6 +528,39 @@ dot_cfi (int arg)
   demand_empty_rest_of_line ();
 }
 
+static void
+dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
+{
+  struct cfi_escape_data *head, **tail, *e;
+  struct cfi_insn_data *insn;
+
+  if (!cur_fde_data)
+    {
+      as_bad (_("CFI instruction used without previous .cfi_startproc"));
+      return;
+    }
+
+  /* If the last address was not at the current PC, advance to current.  */
+  if (symbol_get_frag (last_address) != frag_now
+      || S_GET_VALUE (last_address) != frag_now_fix ())
+    cfi_add_advance_loc (symbol_temp_new_now ());
+
+  tail = &head;
+  do
+    {
+      e = xmalloc (sizeof (*e));
+      do_parse_cons_expression (&e->exp, 1);
+      *tail = e;
+      tail = &e->next;
+    }
+  while (*input_line_pointer++ == ',');
+  *tail = NULL;
+
+  insn = alloc_cfi_insn_data ();
+  insn->insn = CFI_escape;
+  insn->u.esc = head;
+}
+
 static void
 dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
 {
@@ -757,10 +787,17 @@ output_cfi_insn (struct cfi_insn_data *insn)
 
     case DW_CFA_remember_state:
     case DW_CFA_restore_state:
-    case DW_CFA_nop:
       out_one (insn->insn);
       break;
 
+    case CFI_escape:
+      {
+       struct cfi_escape_data *e;
+       for (e = insn->u.esc; e ; e = e->next)
+         emit_expr (&e->exp, 1);
+       break;
+      }
+
     default:
       abort ();
     }
@@ -892,6 +929,10 @@ select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
                goto fail;
              break;
 
+           case CFI_escape:
+             /* Don't bother matching these for now.  */
+             goto fail;
+
            default:
              abort ();
            }
index 0361f97c8f68ff8c9f2b5cbe51a0cbb69ebfa4fa..75b6ec24610abf1bb32bddea2d5bbee4251a3336 100644 (file)
@@ -48,6 +48,5 @@ extern void cfi_add_CFA_undefined (unsigned);
 extern void cfi_add_CFA_same_value (unsigned);
 extern void cfi_add_CFA_remember_state (void);
 extern void cfi_add_CFA_restore_state (void);
-extern void cfi_add_CFA_nop (void);
 
 #endif /* DW2GENCFI_H */
index b7d9190a5b41e43ea434aca5e7c3b598d19daa7c..061dfd41b677c0767f9f5038426536f66ddd90af 100644 (file)
@@ -3346,6 +3346,13 @@ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
 #endif
 #endif
 
+void
+do_parse_cons_expression (expressionS *exp, int nbytes)
+{
+  TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+}
+
+
 /* Worker to do .byte etc statements.
    Clobbers input_line_pointer and checks end-of-line.  */
 
index ba431af704cfd6bfedf6aee5474c6d69160263e9..5a33c703cd003ef760460d51e7f2e585b317b0df 100644 (file)
@@ -133,6 +133,7 @@ extern void stabs_generate_asm_func PARAMS ((const char *, const char *));
 extern void stabs_generate_asm_endfunc PARAMS ((const char *, const char *));
 extern void do_repeat PARAMS((int,const char *,const char *));
 extern void end_repeat PARAMS((int));
+extern void do_parse_cons_expression PARAMS ((expressionS *, int));
 
 extern void generate_lineno_debug PARAMS ((void));
 
index d114c0f2785b6f45bbfff1e66809e700053c6dbc..1ef04ab6d677030a174720c73a5c221df8421599 100644 (file)
@@ -1,3 +1,8 @@
+2003-06-11  Richard Henderson  <rth@redhat.com>
+
+       * gas/cfi/cfi-common-3.[ds]: New.
+       * gas/cfi/cfi.exp: Run it.
+
 2003-06-11  Alan Modra  <amodra@bigpond.net.au>
 
        * gas/macros/app1.d: Ignore section symbols.
diff --git a/gas/testsuite/gas/cfi/cfi-common-3.d b/gas/testsuite/gas/cfi/cfi-common-3.d
new file mode 100644 (file)
index 0000000..f82e02e
--- /dev/null
@@ -0,0 +1,21 @@
+#readelf: -wf
+#name: CFI common 2
+The section .eh_frame contains:
+
+00000000 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: .*
+  Data alignment factor: .*
+  Return address column: .*
+  Augmentation data:     1b
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000014 00000010 00000018 FDE cie=00000000 pc=.*
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_remember_state
+  DW_CFA_restore_state
+
diff --git a/gas/testsuite/gas/cfi/cfi-common-3.s b/gas/testsuite/gas/cfi/cfi-common-3.s
new file mode 100644 (file)
index 0000000..d1282d1
--- /dev/null
@@ -0,0 +1,4 @@
+       .cfi_startproc simple
+       .long 0
+       .cfi_escape 10, 11
+       .cfi_endproc
index 968d3b1918ae83988dd62c8e6a4ede277dd729ab..6592bbefb1382120928ba32a980bb8e53b09c2d8 100644 (file)
@@ -34,3 +34,4 @@ if [istarget "x86_64-*"] then {
 run_list_test "cfi-diag-1" ""
 run_dump_test "cfi-common-1"
 run_dump_test "cfi-common-2"
+run_dump_test "cfi-common-3"