aboutsummaryrefslogtreecommitdiff
path: root/gas/scfidw2gen.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/scfidw2gen.c')
-rw-r--r--gas/scfidw2gen.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/gas/scfidw2gen.c b/gas/scfidw2gen.c
new file mode 100644
index 0000000..1b3fb15
--- /dev/null
+++ b/gas/scfidw2gen.c
@@ -0,0 +1,252 @@
+/* scfidw2gen.c - Support for emission of synthesized Dwarf2 CFI.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS 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.
+
+ GAS 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 GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include "as.h"
+#include "dw2gencfi.h"
+#include "subsegs.h"
+#include "scfidw2gen.h"
+
+#if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
+
+static bool scfi_ignore_warn_once;
+
+static void
+dot_scfi_ignore (int ignored ATTRIBUTE_UNUSED)
+{
+ gas_assert (flag_synth_cfi);
+
+ if (!scfi_ignore_warn_once)
+ {
+ as_warn (_("SCFI ignores most user-specified CFI directives"));
+ scfi_ignore_warn_once = true;
+ }
+ ignore_rest_of_line ();
+}
+
+static void
+scfi_process_cfi_label (void)
+{
+ /* To be implemented. */
+ return;
+}
+
+static void
+scfi_process_cfi_signal_frame (void)
+{
+ /* To be implemented. */
+ return;
+}
+
+static void
+dot_scfi (int arg)
+{
+ switch (arg)
+ {
+ case CFI_label:
+ scfi_process_cfi_label ();
+ break;
+ case CFI_signal_frame:
+ scfi_process_cfi_signal_frame ();
+ break;
+ default:
+ abort ();
+ }
+}
+
+const pseudo_typeS scfi_pseudo_table[] =
+ {
+ { "cfi_sections", dot_cfi_sections, 0 }, /* No ignore. */
+ { "cfi_signal_frame", dot_scfi, CFI_signal_frame }, /* No ignore. */
+ { "cfi_label", dot_scfi, CFI_label }, /* No ignore. */
+ { "cfi_startproc", dot_scfi_ignore, 0 },
+ { "cfi_endproc", dot_scfi_ignore, 0 },
+ { "cfi_fde_data", dot_scfi_ignore, 0 },
+ { "cfi_def_cfa", dot_scfi_ignore, 0 },
+ { "cfi_def_cfa_register", dot_scfi_ignore, 0 },
+ { "cfi_def_cfa_offset", dot_scfi_ignore, 0 },
+ { "cfi_adjust_cfa_offset", dot_scfi_ignore, 0 },
+ { "cfi_offset", dot_scfi_ignore, 0 },
+ { "cfi_rel_offset", dot_scfi_ignore, 0 },
+ { "cfi_register", dot_scfi_ignore, 0 },
+ { "cfi_return_column", dot_scfi_ignore, 0 },
+ { "cfi_restore", dot_scfi_ignore, 0 },
+ { "cfi_undefined", dot_scfi_ignore, 0 },
+ { "cfi_same_value", dot_scfi_ignore, 0 },
+ { "cfi_remember_state", dot_scfi_ignore, 0 },
+ { "cfi_restore_state", dot_scfi_ignore, 0 },
+ { "cfi_window_save", dot_scfi_ignore, 0 },
+ { "cfi_negate_ra_state", dot_scfi_ignore, 0 },
+ { "cfi_escape", dot_scfi_ignore, 0 },
+ { "cfi_personality", dot_scfi_ignore, 0 },
+ { "cfi_personality_id", dot_scfi_ignore, 0 },
+ { "cfi_lsda", dot_scfi_ignore, 0 },
+ { "cfi_val_encoded_addr", dot_scfi_ignore, 0 },
+ { "cfi_inline_lsda", dot_scfi_ignore, 0 },
+ { "cfi_val_offset", dot_scfi_ignore, 0 },
+ { NULL, NULL, 0 }
+ };
+
+void
+scfi_dot_cfi_startproc (const symbolS *start_sym)
+{
+ if (frchain_now->frch_cfi_data != NULL)
+ {
+ as_bad (_("SCFI: missing previous SCFI endproc marker"));
+ return;
+ }
+
+ cfi_new_fde ((symbolS *)start_sym);
+
+ cfi_set_sections ();
+
+ frchain_now->frch_cfi_data->cur_cfa_offset = 0;
+
+ /* By default, SCFI machinery assumes .cfi_startproc is used without
+ parameter simple. */
+ tc_cfi_frame_initial_instructions ();
+
+ if ((all_cfi_sections & CFI_EMIT_target) != 0)
+ tc_cfi_startproc ();
+}
+
+void
+scfi_dot_cfi_endproc (const symbolS *end_sym)
+{
+ struct fde_entry *fde_last;
+
+ if (frchain_now->frch_cfi_data == NULL)
+ {
+ as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
+ return;
+ }
+
+ fde_last = frchain_now->frch_cfi_data->cur_fde_data;
+ cfi_set_last_fde (fde_last);
+
+ cfi_end_fde ((symbolS *)end_sym);
+
+ if ((all_cfi_sections & CFI_EMIT_target) != 0)
+ tc_cfi_endproc (fde_last);
+}
+
+void
+scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset,
+ const char *name, const symbolS *advloc)
+{
+ if (frchain_now->frch_cfi_data == NULL)
+ {
+ as_bad (_("CFI instruction used without previous .cfi_startproc"));
+ return;
+ }
+
+ /* If the last address was not at the current PC, advance to current. */
+ if (frchain_now->frch_cfi_data->last_address != advloc)
+ cfi_add_advance_loc ((symbolS *)advloc);
+
+ switch (arg)
+ {
+ case DW_CFA_offset:
+ cfi_add_CFA_offset (reg1, offset);
+ break;
+
+ case DW_CFA_val_offset:
+ cfi_add_CFA_val_offset (reg1, offset);
+ break;
+
+ case CFI_rel_offset:
+ cfi_add_CFA_offset (reg1,
+ offset - frchain_now->frch_cfi_data->cur_cfa_offset);
+ break;
+
+ case DW_CFA_def_cfa:
+ cfi_add_CFA_def_cfa (reg1, offset);
+ break;
+
+ case DW_CFA_register:
+ cfi_add_CFA_register (reg1, reg2);
+ break;
+
+ case DW_CFA_def_cfa_register:
+ cfi_add_CFA_def_cfa_register (reg1);
+ break;
+
+ case DW_CFA_def_cfa_offset:
+ cfi_add_CFA_def_cfa_offset (offset);
+ break;
+
+ case CFI_adjust_cfa_offset:
+ cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
+ + offset);
+ break;
+
+ case DW_CFA_restore:
+ cfi_add_CFA_restore (reg1);
+ break;
+
+ case DW_CFA_remember_state:
+ cfi_add_CFA_remember_state ();
+ break;
+
+ case DW_CFA_restore_state:
+ cfi_add_CFA_restore_state ();
+ break;
+
+ case CFI_label:
+ cfi_add_label (name);
+ break;
+
+ case CFI_signal_frame:
+ frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
+ break;
+
+/*
+ case DW_CFA_undefined:
+ for (;;)
+ {
+ reg1 = cfi_parse_reg ();
+ cfi_add_CFA_undefined (reg1);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ break;
+ ++input_line_pointer;
+ }
+ break;
+
+ case DW_CFA_same_value:
+ reg1 = cfi_parse_reg ();
+ cfi_add_CFA_same_value (reg1);
+ break;
+
+ case CFI_return_column:
+ reg1 = cfi_parse_reg ();
+ cfi_set_return_column (reg1);
+ break;
+
+ case DW_CFA_GNU_window_save:
+ cfi_add_CFA_insn (DW_CFA_GNU_window_save);
+ break;
+
+*/
+ default:
+ abort ();
+ }
+}
+
+#endif