* dw2gencfi.c (struct cfa_save_data, cfa_save_stack): New.
authorRichard Henderson <rth@redhat.com>
Sun, 8 Jun 2003 03:59:44 +0000 (03:59 +0000)
committerRichard Henderson <rth@redhat.com>
Sun, 8 Jun 2003 03:59:44 +0000 (03:59 +0000)
        (cfi_add_CFA_offset): Detect invalid offsets.
        (cfi_add_CFA_remember_state): Save cur_cfa_offset.
        (cfi_add_CFA_restore_state): Restore it.
        (CFI_rel_offset): New.
        (cfi_pseudo_table): Add it.
        (dot_cfi): Handle it.

        * gas/cfi/cfi-common-1.d, gas/cfi/cfi-common-1.s: New.
        * gas/cfi/cfi-common-2.d, gas/cfi/cfi-common-2.s: New.
        * gas/cfi/cfi-diag-1.d, gas/cfi/cfi-diag-1.s: New.
        * gas/cfi/cfi.exp: Run them.

gas/ChangeLog
gas/dw2gencfi.c
gas/testsuite/ChangeLog
gas/testsuite/gas/cfi/cfi-common-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-common-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-common-2.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-common-2.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-diag-1.l [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-diag-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi.exp

index 8f5aa936130cd48d99530395a30181e1c97707eb..799898f96dff4763da7960827d1c9614c25bad30 100644 (file)
@@ -1,3 +1,13 @@
+2003-06-07  Richard Henderson  <rth@redhat.com>
+
+       * dw2gencfi.c (struct cfa_save_data, cfa_save_stack): New.
+       (cfi_add_CFA_offset): Detect invalid offsets.
+       (cfi_add_CFA_remember_state): Save cur_cfa_offset.
+       (cfi_add_CFA_restore_state): Restore it.
+       (CFI_rel_offset): New.
+       (cfi_pseudo_table): Add it.
+       (dot_cfi): Handle it.
+
 2003-06-07  H.J. Lu <hongjiu.lu@intel.com>
 
        * app.c (do_scrub_chars): Add states 14 and 15 to handle
index 5e378337e32140268405542054bfdeeece755d21..ccfb1103a16bdf4705953c8c1a6cc5a5059e0c5a 100644 (file)
@@ -102,6 +102,14 @@ static struct fde_entry **last_fde_data = &all_fde_data;
 /* List of CIEs so that they could be reused.  */
 static struct cie_entry *cie_root;
 
+/* Stack of old CFI data, for save/restore.  */
+struct cfa_save_data
+{
+  struct cfa_save_data *next;
+  offsetT cfa_offset;
+};
+
+static struct cfa_save_data *cfa_save_stack;
 \f
 /* Construct a new FDE structure and add it to the end of the fde list.  */
 
@@ -231,7 +239,14 @@ cfi_add_advance_loc (symbolS *label)
 void
 cfi_add_CFA_offset (unsigned regno, offsetT offset)
 {
+  unsigned int abs_data_align;
+
   cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
+
+  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
+                   ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
+  if (offset % abs_data_align)
+    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
 }
 
 /* Add a DW_CFA_def_cfa record to the CFI data.  */
@@ -289,13 +304,30 @@ cfi_add_CFA_same_value (unsigned regno)
 void
 cfi_add_CFA_remember_state (void)
 {
+  struct cfa_save_data *p;
+
   cfi_add_CFA_insn (DW_CFA_remember_state);
+
+  p = xmalloc (sizeof (*p));
+  p->cfa_offset = cur_cfa_offset;
+  p->next = cfa_save_stack;
+  cfa_save_stack = p;
 }
 
 void
 cfi_add_CFA_restore_state (void)
 {
+  struct cfa_save_data *p;
+
   cfi_add_CFA_insn (DW_CFA_restore_state);
+
+  p = cfa_save_stack;
+  if (p)
+    {
+      cur_cfa_offset = p->cfa_offset;
+      cfa_save_stack = p->next;
+      free (p);
+    }
 }
 
 void
@@ -314,6 +346,7 @@ static void dot_cfi_endproc (int);
 /* Fake CFI type; outside the byte range of any real CFI insn.  */
 #define CFI_adjust_cfa_offset  0x100
 #define CFI_return_column      0x101
+#define CFI_rel_offset         0x102
 
 const pseudo_typeS cfi_pseudo_table[] =
   {
@@ -324,6 +357,7 @@ const pseudo_typeS cfi_pseudo_table[] =
     { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
     { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
     { "cfi_offset", dot_cfi, DW_CFA_offset },
+    { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
     { "cfi_register", dot_cfi, DW_CFA_register },
     { "cfi_return_column", dot_cfi, CFI_return_column },
     { "cfi_restore", dot_cfi, DW_CFA_restore },
@@ -422,6 +456,13 @@ dot_cfi (int arg)
       cfi_add_CFA_offset (reg1, offset);
       break;
 
+    case CFI_rel_offset:
+      reg1 = cfi_parse_reg ();
+      cfi_parse_separator ();
+      offset = cfi_parse_const ();
+      cfi_add_CFA_offset (reg1, offset - cur_cfa_offset);
+      break;
+
     case DW_CFA_def_cfa:
       reg1 = cfi_parse_reg ();
       cfi_parse_separator ();
index 665da6ae20a6e88e84a11f21cc48c0cc1ab2f604..6d895a050bb504d9440e61b33543fa152f02e0f1 100644 (file)
@@ -1,3 +1,10 @@
+2003-06-07  Richard Henderson  <rth@redhat.com>
+
+       * gas/cfi/cfi-common-1.d, gas/cfi/cfi-common-1.s: New.
+       * gas/cfi/cfi-common-2.d, gas/cfi/cfi-common-2.s: New.
+       * gas/cfi/cfi-diag-1.d, gas/cfi/cfi-diag-1.s: New.
+       * gas/cfi/cfi.exp: Run them.
+
 2003-06-05  Michael Snyder  <msnyder@redhat.com>
 
        * gas/h8300/t01_mov.s: New file, tests mov instructions.
diff --git a/gas/testsuite/gas/cfi/cfi-common-1.d b/gas/testsuite/gas/cfi/cfi-common-1.d
new file mode 100644 (file)
index 0000000..8e7db37
--- /dev/null
@@ -0,0 +1,24 @@
+#readelf: -wf
+#name: CFI common 1
+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 00000018 00000018 FDE cie=00000000 pc=.*
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa: r0 ofs 16
+  DW_CFA_offset: r1 at cfa-8
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa_offset: 32
+  DW_CFA_offset: r2 at cfa-24
+
diff --git a/gas/testsuite/gas/cfi/cfi-common-1.s b/gas/testsuite/gas/cfi/cfi-common-1.s
new file mode 100644 (file)
index 0000000..72db279
--- /dev/null
@@ -0,0 +1,8 @@
+       .cfi_startproc simple
+       .long 0
+       .cfi_def_cfa 0, 16
+       .cfi_rel_offset 1, 8
+       .long 0
+       .cfi_adjust_cfa_offset 16
+       .cfi_rel_offset 2, 8
+       .cfi_endproc
diff --git a/gas/testsuite/gas/cfi/cfi-common-2.d b/gas/testsuite/gas/cfi/cfi-common-2.d
new file mode 100644 (file)
index 0000000..03f0d88
--- /dev/null
@@ -0,0 +1,29 @@
+#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 0000001c 00000018 FDE cie=00000000 pc=.*
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa: r0 ofs 16
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_remember_state
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa_offset: 0
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_restore_state
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa_offset: 0
+  DW_CFA_nop
+
diff --git a/gas/testsuite/gas/cfi/cfi-common-2.s b/gas/testsuite/gas/cfi/cfi-common-2.s
new file mode 100644 (file)
index 0000000..e2a9443
--- /dev/null
@@ -0,0 +1,12 @@
+       .cfi_startproc simple
+       .long 0
+       .cfi_def_cfa 0, 16
+       .long 0
+       .cfi_remember_state
+       .long 0
+       .cfi_adjust_cfa_offset -16
+       .long 0
+       .cfi_restore_state
+       .long 0
+       .cfi_adjust_cfa_offset -16
+       .cfi_endproc
diff --git a/gas/testsuite/gas/cfi/cfi-diag-1.l b/gas/testsuite/gas/cfi/cfi-diag-1.l
new file mode 100644 (file)
index 0000000..3dc8a61
--- /dev/null
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:2: Error: register save offset not a multiple of .*
diff --git a/gas/testsuite/gas/cfi/cfi-diag-1.s b/gas/testsuite/gas/cfi/cfi-diag-1.s
new file mode 100644 (file)
index 0000000..de0f865
--- /dev/null
@@ -0,0 +1,3 @@
+       .cfi_startproc
+       .cfi_offset 0, 1
+       .cfi_endproc
index 0c24682ff365571448f82a09e2342a78b7f29905..88baac251502d501cf4dd235550febb19e6f51ca 100644 (file)
@@ -1,9 +1,27 @@
+# ??? This probably shouldn't be replicated here...
+proc run_list_test { name opts } {
+    global srcdir subdir
+    set testname "cfi $name"
+    set file $srcdir/$subdir/$name
+    gas_run ${name}.s $opts ">&dump.out"
+    if { [regexp_diff "dump.out" "${file}.l"] } then {
+        fail $testname
+        verbose "output is [file_contents "dump.out"]" 2
+        return
+    }
+    pass $testname
+}
+
+set any "0"
+
 if [istarget "x86_64-*"] then {
     run_dump_test "cfi-x86_64"
+    set any "1"
 }
 
 if [istarget "i?86-*"] then {
     run_dump_test "cfi-i386"
+    set any "1"
 }
 
 if { [istarget alpha*-*-*] } then {
@@ -17,5 +35,12 @@ if { [istarget alpha*-*-*] } then {
        run_dump_test "cfi-alpha-1"
        run_dump_test "cfi-alpha-2"
        run_dump_test "cfi-alpha-3"
+       set any "1"
     }
 }
+
+if $any {
+    run_list_test "cfi-diag-1" ""
+    run_dump_test "cfi-common-1"
+    run_dump_test "cfi-common-2"
+}