xref: /netbsd-src/external/gpl3/binutils/dist/gas/scfidw2gen.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1*cb63e24eSchristos /* scfidw2gen.c - Support for emission of synthesized Dwarf2 CFI.
2*cb63e24eSchristos    Copyright (C) 2023 Free Software Foundation, Inc.
3*cb63e24eSchristos 
4*cb63e24eSchristos    This file is part of GAS, the GNU Assembler.
5*cb63e24eSchristos 
6*cb63e24eSchristos    GAS is free software; you can redistribute it and/or modify
7*cb63e24eSchristos    it under the terms of the GNU General Public License as published by
8*cb63e24eSchristos    the Free Software Foundation; either version 3, or (at your option)
9*cb63e24eSchristos    any later version.
10*cb63e24eSchristos 
11*cb63e24eSchristos    GAS is distributed in the hope that it will be useful,
12*cb63e24eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cb63e24eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*cb63e24eSchristos    GNU General Public License for more details.
15*cb63e24eSchristos 
16*cb63e24eSchristos    You should have received a copy of the GNU General Public License
17*cb63e24eSchristos    along with GAS; see the file COPYING.  If not, write to the Free
18*cb63e24eSchristos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19*cb63e24eSchristos    02110-1301, USA.  */
20*cb63e24eSchristos 
21*cb63e24eSchristos #include "as.h"
22*cb63e24eSchristos #include "ginsn.h"
23*cb63e24eSchristos #include "scfi.h"
24*cb63e24eSchristos #include "dw2gencfi.h"
25*cb63e24eSchristos #include "subsegs.h"
26*cb63e24eSchristos #include "scfidw2gen.h"
27*cb63e24eSchristos 
28*cb63e24eSchristos #if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
29*cb63e24eSchristos 
30*cb63e24eSchristos static bool scfi_ignore_warn_once;
31*cb63e24eSchristos 
32*cb63e24eSchristos static void
dot_scfi_ignore(int ignored ATTRIBUTE_UNUSED)33*cb63e24eSchristos dot_scfi_ignore (int ignored ATTRIBUTE_UNUSED)
34*cb63e24eSchristos {
35*cb63e24eSchristos   gas_assert (flag_synth_cfi);
36*cb63e24eSchristos 
37*cb63e24eSchristos   if (!scfi_ignore_warn_once)
38*cb63e24eSchristos     {
39*cb63e24eSchristos       as_warn (_("SCFI ignores most user-specified CFI directives"));
40*cb63e24eSchristos       scfi_ignore_warn_once = true;
41*cb63e24eSchristos     }
42*cb63e24eSchristos   ignore_rest_of_line ();
43*cb63e24eSchristos }
44*cb63e24eSchristos 
45*cb63e24eSchristos static void
scfi_process_cfi_label(void)46*cb63e24eSchristos scfi_process_cfi_label (void)
47*cb63e24eSchristos {
48*cb63e24eSchristos   char *name;
49*cb63e24eSchristos   ginsnS *ginsn;
50*cb63e24eSchristos 
51*cb63e24eSchristos   name = read_symbol_name ();
52*cb63e24eSchristos   if (name == NULL)
53*cb63e24eSchristos     return;
54*cb63e24eSchristos 
55*cb63e24eSchristos   /* Add a new ginsn.  */
56*cb63e24eSchristos   ginsn = ginsn_new_phantom (symbol_temp_new_now ());
57*cb63e24eSchristos   frch_ginsn_data_append (ginsn);
58*cb63e24eSchristos 
59*cb63e24eSchristos   scfi_op_add_cfi_label (ginsn, name);
60*cb63e24eSchristos   /* TODO.  */
61*cb63e24eSchristos   // free (name);
62*cb63e24eSchristos 
63*cb63e24eSchristos   demand_empty_rest_of_line ();
64*cb63e24eSchristos }
65*cb63e24eSchristos 
66*cb63e24eSchristos static void
scfi_process_cfi_signal_frame(void)67*cb63e24eSchristos scfi_process_cfi_signal_frame (void)
68*cb63e24eSchristos {
69*cb63e24eSchristos   ginsnS *ginsn;
70*cb63e24eSchristos 
71*cb63e24eSchristos   ginsn = ginsn_new_phantom (symbol_temp_new_now ());
72*cb63e24eSchristos   frch_ginsn_data_append (ginsn);
73*cb63e24eSchristos 
74*cb63e24eSchristos   scfi_op_add_signal_frame (ginsn);
75*cb63e24eSchristos }
76*cb63e24eSchristos 
77*cb63e24eSchristos static void
dot_scfi(int arg)78*cb63e24eSchristos dot_scfi (int arg)
79*cb63e24eSchristos {
80*cb63e24eSchristos   switch (arg)
81*cb63e24eSchristos     {
82*cb63e24eSchristos       case CFI_label:
83*cb63e24eSchristos 	scfi_process_cfi_label ();
84*cb63e24eSchristos 	break;
85*cb63e24eSchristos       case CFI_signal_frame:
86*cb63e24eSchristos 	scfi_process_cfi_signal_frame ();
87*cb63e24eSchristos 	break;
88*cb63e24eSchristos       default:
89*cb63e24eSchristos 	abort ();
90*cb63e24eSchristos     }
91*cb63e24eSchristos }
92*cb63e24eSchristos 
93*cb63e24eSchristos const pseudo_typeS scfi_pseudo_table[] =
94*cb63e24eSchristos   {
95*cb63e24eSchristos     { "cfi_sections", dot_cfi_sections, 0 }, /* No ignore.  */
96*cb63e24eSchristos     { "cfi_signal_frame", dot_scfi, CFI_signal_frame }, /* No ignore.  */
97*cb63e24eSchristos     { "cfi_label", dot_scfi, CFI_label }, /* No ignore.  */
98*cb63e24eSchristos     { "cfi_startproc", dot_scfi_ignore, 0 },
99*cb63e24eSchristos     { "cfi_endproc", dot_scfi_ignore, 0 },
100*cb63e24eSchristos     { "cfi_fde_data", dot_scfi_ignore, 0 },
101*cb63e24eSchristos     { "cfi_def_cfa", dot_scfi_ignore, 0 },
102*cb63e24eSchristos     { "cfi_def_cfa_register", dot_scfi_ignore, 0 },
103*cb63e24eSchristos     { "cfi_def_cfa_offset", dot_scfi_ignore, 0 },
104*cb63e24eSchristos     { "cfi_adjust_cfa_offset", dot_scfi_ignore, 0 },
105*cb63e24eSchristos     { "cfi_offset", dot_scfi_ignore, 0 },
106*cb63e24eSchristos     { "cfi_rel_offset", dot_scfi_ignore, 0 },
107*cb63e24eSchristos     { "cfi_register", dot_scfi_ignore, 0 },
108*cb63e24eSchristos     { "cfi_return_column", dot_scfi_ignore, 0 },
109*cb63e24eSchristos     { "cfi_restore", dot_scfi_ignore, 0 },
110*cb63e24eSchristos     { "cfi_undefined", dot_scfi_ignore, 0 },
111*cb63e24eSchristos     { "cfi_same_value", dot_scfi_ignore, 0 },
112*cb63e24eSchristos     { "cfi_remember_state", dot_scfi_ignore, 0 },
113*cb63e24eSchristos     { "cfi_restore_state", dot_scfi_ignore, 0 },
114*cb63e24eSchristos     { "cfi_window_save", dot_scfi_ignore, 0 },
115*cb63e24eSchristos     { "cfi_negate_ra_state", dot_scfi_ignore, 0 },
116*cb63e24eSchristos     { "cfi_escape", dot_scfi_ignore, 0 },
117*cb63e24eSchristos     { "cfi_personality", dot_scfi_ignore, 0 },
118*cb63e24eSchristos     { "cfi_personality_id", dot_scfi_ignore, 0 },
119*cb63e24eSchristos     { "cfi_lsda", dot_scfi_ignore, 0 },
120*cb63e24eSchristos     { "cfi_val_encoded_addr", dot_scfi_ignore, 0 },
121*cb63e24eSchristos     { "cfi_inline_lsda", dot_scfi_ignore, 0 },
122*cb63e24eSchristos     { "cfi_val_offset", dot_scfi_ignore, 0 },
123*cb63e24eSchristos     { NULL, NULL, 0 }
124*cb63e24eSchristos   };
125*cb63e24eSchristos 
126*cb63e24eSchristos void
scfi_dot_cfi_startproc(const symbolS * start_sym)127*cb63e24eSchristos scfi_dot_cfi_startproc (const symbolS *start_sym)
128*cb63e24eSchristos {
129*cb63e24eSchristos   if (frchain_now->frch_cfi_data != NULL)
130*cb63e24eSchristos     {
131*cb63e24eSchristos       as_bad (_("SCFI: missing previous SCFI endproc marker"));
132*cb63e24eSchristos       return;
133*cb63e24eSchristos     }
134*cb63e24eSchristos 
135*cb63e24eSchristos   cfi_new_fde ((symbolS *)start_sym);
136*cb63e24eSchristos 
137*cb63e24eSchristos   cfi_set_sections ();
138*cb63e24eSchristos 
139*cb63e24eSchristos   frchain_now->frch_cfi_data->cur_cfa_offset = 0;
140*cb63e24eSchristos 
141*cb63e24eSchristos   /* By default, SCFI machinery assumes .cfi_startproc is used without
142*cb63e24eSchristos      parameter simple.  */
143*cb63e24eSchristos   tc_cfi_frame_initial_instructions ();
144*cb63e24eSchristos 
145*cb63e24eSchristos   if ((all_cfi_sections & CFI_EMIT_target) != 0)
146*cb63e24eSchristos     tc_cfi_startproc ();
147*cb63e24eSchristos }
148*cb63e24eSchristos 
149*cb63e24eSchristos void
scfi_dot_cfi_endproc(const symbolS * end_sym)150*cb63e24eSchristos scfi_dot_cfi_endproc (const symbolS *end_sym)
151*cb63e24eSchristos {
152*cb63e24eSchristos   struct fde_entry *fde_last;
153*cb63e24eSchristos 
154*cb63e24eSchristos   if (frchain_now->frch_cfi_data == NULL)
155*cb63e24eSchristos     {
156*cb63e24eSchristos       as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
157*cb63e24eSchristos       return;
158*cb63e24eSchristos     }
159*cb63e24eSchristos 
160*cb63e24eSchristos   fde_last = frchain_now->frch_cfi_data->cur_fde_data;
161*cb63e24eSchristos   cfi_set_last_fde (fde_last);
162*cb63e24eSchristos 
163*cb63e24eSchristos   cfi_end_fde ((symbolS *)end_sym);
164*cb63e24eSchristos 
165*cb63e24eSchristos   if ((all_cfi_sections & CFI_EMIT_target) != 0)
166*cb63e24eSchristos     tc_cfi_endproc (fde_last);
167*cb63e24eSchristos }
168*cb63e24eSchristos 
169*cb63e24eSchristos void
scfi_dot_cfi(int arg,unsigned reg1,unsigned reg2,offsetT offset,const char * name,const symbolS * advloc)170*cb63e24eSchristos scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset,
171*cb63e24eSchristos 	      const char *name, const symbolS *advloc)
172*cb63e24eSchristos {
173*cb63e24eSchristos   if (frchain_now->frch_cfi_data == NULL)
174*cb63e24eSchristos     {
175*cb63e24eSchristos       as_bad (_("CFI instruction used without previous .cfi_startproc"));
176*cb63e24eSchristos       return;
177*cb63e24eSchristos     }
178*cb63e24eSchristos 
179*cb63e24eSchristos   /* If the last address was not at the current PC, advance to current.  */
180*cb63e24eSchristos   if (frchain_now->frch_cfi_data->last_address != advloc)
181*cb63e24eSchristos     cfi_add_advance_loc ((symbolS *)advloc);
182*cb63e24eSchristos 
183*cb63e24eSchristos   switch (arg)
184*cb63e24eSchristos     {
185*cb63e24eSchristos     case DW_CFA_offset:
186*cb63e24eSchristos       cfi_add_CFA_offset (reg1, offset);
187*cb63e24eSchristos       break;
188*cb63e24eSchristos 
189*cb63e24eSchristos     case DW_CFA_val_offset:
190*cb63e24eSchristos       cfi_add_CFA_val_offset (reg1, offset);
191*cb63e24eSchristos       break;
192*cb63e24eSchristos 
193*cb63e24eSchristos     case CFI_rel_offset:
194*cb63e24eSchristos       cfi_add_CFA_offset (reg1,
195*cb63e24eSchristos 			  offset - frchain_now->frch_cfi_data->cur_cfa_offset);
196*cb63e24eSchristos       break;
197*cb63e24eSchristos 
198*cb63e24eSchristos     case DW_CFA_def_cfa:
199*cb63e24eSchristos       cfi_add_CFA_def_cfa (reg1, offset);
200*cb63e24eSchristos       break;
201*cb63e24eSchristos 
202*cb63e24eSchristos     case DW_CFA_register:
203*cb63e24eSchristos       cfi_add_CFA_register (reg1, reg2);
204*cb63e24eSchristos       break;
205*cb63e24eSchristos 
206*cb63e24eSchristos     case DW_CFA_def_cfa_register:
207*cb63e24eSchristos       cfi_add_CFA_def_cfa_register (reg1);
208*cb63e24eSchristos       break;
209*cb63e24eSchristos 
210*cb63e24eSchristos     case DW_CFA_def_cfa_offset:
211*cb63e24eSchristos       cfi_add_CFA_def_cfa_offset (offset);
212*cb63e24eSchristos       break;
213*cb63e24eSchristos 
214*cb63e24eSchristos     case CFI_adjust_cfa_offset:
215*cb63e24eSchristos       cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
216*cb63e24eSchristos 				  + offset);
217*cb63e24eSchristos       break;
218*cb63e24eSchristos 
219*cb63e24eSchristos     case DW_CFA_restore:
220*cb63e24eSchristos       cfi_add_CFA_restore (reg1);
221*cb63e24eSchristos       break;
222*cb63e24eSchristos 
223*cb63e24eSchristos     case DW_CFA_remember_state:
224*cb63e24eSchristos       cfi_add_CFA_remember_state ();
225*cb63e24eSchristos       break;
226*cb63e24eSchristos 
227*cb63e24eSchristos     case DW_CFA_restore_state:
228*cb63e24eSchristos       cfi_add_CFA_restore_state ();
229*cb63e24eSchristos       break;
230*cb63e24eSchristos 
231*cb63e24eSchristos     case CFI_label:
232*cb63e24eSchristos       cfi_add_label (name);
233*cb63e24eSchristos       break;
234*cb63e24eSchristos 
235*cb63e24eSchristos     case CFI_signal_frame:
236*cb63e24eSchristos       frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
237*cb63e24eSchristos       break;
238*cb63e24eSchristos 
239*cb63e24eSchristos /*
240*cb63e24eSchristos     case DW_CFA_undefined:
241*cb63e24eSchristos       for (;;)
242*cb63e24eSchristos 	{
243*cb63e24eSchristos 	  reg1 = cfi_parse_reg ();
244*cb63e24eSchristos 	  cfi_add_CFA_undefined (reg1);
245*cb63e24eSchristos 	  SKIP_WHITESPACE ();
246*cb63e24eSchristos 	  if (*input_line_pointer != ',')
247*cb63e24eSchristos 	    break;
248*cb63e24eSchristos 	  ++input_line_pointer;
249*cb63e24eSchristos 	}
250*cb63e24eSchristos       break;
251*cb63e24eSchristos 
252*cb63e24eSchristos     case DW_CFA_same_value:
253*cb63e24eSchristos       reg1 = cfi_parse_reg ();
254*cb63e24eSchristos       cfi_add_CFA_same_value (reg1);
255*cb63e24eSchristos       break;
256*cb63e24eSchristos 
257*cb63e24eSchristos     case CFI_return_column:
258*cb63e24eSchristos       reg1 = cfi_parse_reg ();
259*cb63e24eSchristos       cfi_set_return_column (reg1);
260*cb63e24eSchristos       break;
261*cb63e24eSchristos 
262*cb63e24eSchristos     case DW_CFA_GNU_window_save:
263*cb63e24eSchristos       cfi_add_CFA_insn (DW_CFA_GNU_window_save);
264*cb63e24eSchristos       break;
265*cb63e24eSchristos 
266*cb63e24eSchristos */
267*cb63e24eSchristos     default:
268*cb63e24eSchristos       abort ();
269*cb63e24eSchristos     }
270*cb63e24eSchristos }
271*cb63e24eSchristos 
272*cb63e24eSchristos #endif
273