1/* ginsn.h - GAS instruction representation.
2   Copyright (C) 2023 Free Software Foundation, Inc.
3
4   This file is part of GAS, the GNU Assembler.
5
6   GAS is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3, or (at your option)
9   any later version.
10
11   GAS is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with GAS; see the file COPYING.  If not, write to the Free
18   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19   02110-1301, USA.  */
20
21#ifndef GINSN_H
22#define GINSN_H
23
24#include "as.h"
25
26/* Maximum number of source operands of a ginsn.  */
27#define GINSN_NUM_SRC_OPNDS   2
28
29/* A ginsn in printed in the following format:
30      "ginsn: OPCD SRC1, SRC2, DST"
31      "<-5->  <--------125------->"
32   where each of SRC1, SRC2, and DST are in the form:
33      "%rNN,"  (up to 5 chars)
34      "imm,"   (up to int32_t+1 chars)
35      "[%rNN+-imm]," (up to int32_t+9 chars)
36      Hence a max of 19 chars.  */
37
38#define GINSN_LISTING_OPND_LEN	40
39#define GINSN_LISTING_LEN 156
40
41enum ginsn_gen_mode
42{
43  GINSN_GEN_NONE,
44  /* Generate ginsns for program validation passes.  */
45  GINSN_GEN_FVAL,
46  /* Generate ginsns for synthesizing DWARF CFI.  */
47  GINSN_GEN_SCFI,
48};
49
50/* ginsn types.
51
52   GINSN_TYPE_PHANTOM are phantom ginsns.  They are used where there is no real
53   machine instruction counterpart, but a ginsn is needed only to carry
54   information to GAS.  For example, to carry an SCFI Op.
55
56   Note that, ginsns do not have a push / pop instructions.
57   Instead, following are used:
58      type=GINSN_TYPE_LOAD, src=GINSN_SRC_INDIRECT, REG_SP: Load from stack.
59      type=GINSN_TYPE_STORE, dst=GINSN_DST_INDIRECT, REG_SP: Store to stack.
60*/
61
62#define _GINSN_TYPES \
63  _GINSN_TYPE_ITEM (GINSN_TYPE_SYMBOL, "SYM") \
64  _GINSN_TYPE_ITEM (GINSN_TYPE_PHANTOM, "PHANTOM")  \
65  _GINSN_TYPE_ITEM (GINSN_TYPE_ADD, "ADD")  \
66  _GINSN_TYPE_ITEM (GINSN_TYPE_AND, "AND")  \
67  _GINSN_TYPE_ITEM (GINSN_TYPE_CALL, "CALL") \
68  _GINSN_TYPE_ITEM (GINSN_TYPE_JUMP, "JMP") \
69  _GINSN_TYPE_ITEM (GINSN_TYPE_JUMP_COND, "JCC")  \
70  _GINSN_TYPE_ITEM (GINSN_TYPE_MOV, "MOV")  \
71  _GINSN_TYPE_ITEM (GINSN_TYPE_LOAD, "LOAD")  \
72  _GINSN_TYPE_ITEM (GINSN_TYPE_STORE, "STORE")  \
73  _GINSN_TYPE_ITEM (GINSN_TYPE_RETURN, "RET") \
74  _GINSN_TYPE_ITEM (GINSN_TYPE_SUB, "SUB")  \
75  _GINSN_TYPE_ITEM (GINSN_TYPE_OTHER, "OTH")
76
77enum ginsn_type
78{
79#define _GINSN_TYPE_ITEM(NAME, STR) NAME,
80  _GINSN_TYPES
81#undef _GINSN_TYPE_ITEM
82};
83
84enum ginsn_src_type
85{
86  GINSN_SRC_UNKNOWN,
87  GINSN_SRC_REG,
88  GINSN_SRC_IMM,
89  GINSN_SRC_INDIRECT,
90  GINSN_SRC_SYMBOL,
91};
92
93/* GAS instruction source operand representation.  */
94
95struct ginsn_src
96{
97  enum ginsn_src_type type;
98  /* DWARF register number.  */
99  unsigned int reg;
100  /* Immediate or disp for indirect memory access.  */
101  offsetT immdisp;
102  /* Src symbol.  May be needed for some control flow instructions.  */
103  const symbolS *sym;
104};
105
106enum ginsn_dst_type
107{
108  GINSN_DST_UNKNOWN,
109  GINSN_DST_REG,
110  GINSN_DST_INDIRECT,
111};
112
113/* GAS instruction destination operand representation.  */
114
115struct ginsn_dst
116{
117  enum ginsn_dst_type type;
118  /* DWARF register number.  */
119  unsigned int reg;
120  /* Disp for indirect memory access.  */
121  offsetT disp;
122};
123
124/* Various flags for additional information per GAS instruction.  */
125
126/* Function begin or end symbol.  */
127#define GINSN_F_FUNC_MARKER	    0x1
128/* Identify real or implicit GAS insn.
129   Some targets employ CISC-like instructions.  Multiple ginsn's may be used
130   for a single machine instruction in some ISAs.  For some optimizations,
131   there is need to identify whether a ginsn, e.g., GINSN_TYPE_ADD or
132   GINSN_TYPE_SUB is a result of an user-specified instruction or not.  */
133#define GINSN_F_INSN_REAL	    0x2
134/* Identify if the GAS insn of type GINSN_TYPE_SYMBOL is due to a user-defined
135   label.  Each user-defined labels in a function will cause addition of a new
136   ginsn.  This simplifies control flow graph creation.
137   See htab_t label_ginsn_map usage.  */
138#define GINSN_F_USER_LABEL	    0x4
139/* Max bit position for flags (uint32_t).  */
140#define GINSN_F_MAX		    0x20
141
142#define GINSN_F_FUNC_BEGIN_P(ginsn)	    \
143  ((ginsn != NULL)			    \
144   && (ginsn->type == GINSN_TYPE_SYMBOL)    \
145   && (ginsn->flags & GINSN_F_FUNC_MARKER))
146
147/* PS: For ginsn associated with a user-defined symbol location,
148   GINSN_F_FUNC_MARKER is unset, but GINSN_F_USER_LABEL is set.  */
149#define GINSN_F_FUNC_END_P(ginsn)	    \
150  ((ginsn != NULL)			    \
151   && (ginsn->type == GINSN_TYPE_SYMBOL)    \
152   && !(ginsn->flags & GINSN_F_FUNC_MARKER) \
153   && !(ginsn->flags & GINSN_F_USER_LABEL))
154
155#define GINSN_F_INSN_REAL_P(ginsn)	    \
156  ((ginsn != NULL)			    \
157   && (ginsn->flags & GINSN_F_INSN_REAL))
158
159#define GINSN_F_USER_LABEL_P(ginsn)	    \
160  ((ginsn != NULL)			    \
161   && (ginsn->type == GINSN_TYPE_SYMBOL)    \
162   && !(ginsn->flags & GINSN_F_FUNC_MARKER) \
163   && (ginsn->flags & GINSN_F_USER_LABEL))
164
165typedef struct ginsn ginsnS;
166typedef struct scfi_op scfi_opS;
167typedef struct scfi_state scfi_stateS;
168
169/* GAS generic instruction.
170
171   Generic instructions are used by GAS to abstract out the binary machine
172   instructions.  In other words, ginsn is a target/ABI independent internal
173   representation for GAS.  Note that, depending on the target, there may be
174   more than one ginsn per binary machine instruction.
175
176   ginsns can be used by GAS to perform validations, or even generate
177   additional information like, sythesizing DWARF CFI for hand-written asm.  */
178
179struct ginsn
180{
181  enum ginsn_type type;
182  /* GAS instructions are simple instructions with GINSN_NUM_SRC_OPNDS number
183     of source operands and one destination operand at this time.  */
184  struct ginsn_src src[GINSN_NUM_SRC_OPNDS];
185  struct ginsn_dst dst;
186  /* Additional information per instruction.  */
187  uint32_t flags;
188  /* Symbol.  For ginsn of type other than GINSN_TYPE_SYMBOL, this identifies
189     the end of the corresponding machine instruction in the .text segment.
190     These symbols are created anew by the targets and are not used elsewhere
191     in GAS.  The only exception is some ginsns of type GINSN_TYPE_SYMBOL, when
192     generated for the user-defined labels.  See ginsn_frob_label.  */
193  const symbolS *sym;
194  /* Identifier (linearly increasing natural number) for each ginsn.  Used as
195     a proxy for program order of ginsns.  */
196  uint64_t id;
197  /* Location information for user-interfacing messaging.  Only ginsns with
198     GINSN_F_FUNC_BEGIN_P and GINSN_F_FUNC_END_P may present themselves with no
199     file or line information.  */
200  const char *file;
201  unsigned int line;
202
203  /* Information needed for synthesizing CFI.  */
204  scfi_opS **scfi_ops;
205  uint32_t num_scfi_ops;
206
207  /* Flag to keep track of visited instructions for CFG creation.  */
208  bool visited;
209
210  ginsnS *next; /* A linked list.  */
211};
212
213struct ginsn_src *ginsn_get_src1 (ginsnS *ginsn);
214struct ginsn_src *ginsn_get_src2 (ginsnS *ginsn);
215struct ginsn_dst *ginsn_get_dst (ginsnS *ginsn);
216
217unsigned int ginsn_get_src_reg (struct ginsn_src *src);
218enum ginsn_src_type ginsn_get_src_type (struct ginsn_src *src);
219offsetT ginsn_get_src_disp (struct ginsn_src *src);
220offsetT ginsn_get_src_imm (struct ginsn_src *src);
221
222unsigned int ginsn_get_dst_reg (struct ginsn_dst *dst);
223enum ginsn_dst_type ginsn_get_dst_type (struct ginsn_dst *dst);
224offsetT ginsn_get_dst_disp (struct ginsn_dst *dst);
225
226/* Data object for book-keeping information related to GAS generic
227   instructions.  */
228struct frch_ginsn_data
229{
230  /* Mode for GINSN creation.  */
231  enum ginsn_gen_mode mode;
232  /* Head of the list of ginsns.  */
233  ginsnS *gins_rootP;
234  /* Tail of the list of ginsns.  */
235  ginsnS *gins_lastP;
236  /* Function symbol.  */
237  const symbolS *func;
238  /* Start address of the function.  */
239  symbolS *start_addr;
240  /* User-defined label to ginsn mapping.  */
241  htab_t label_ginsn_map;
242  /* Is the list of ginsn apt for creating CFG.  */
243  bool gcfg_apt_p;
244};
245
246int ginsn_data_begin (const symbolS *func);
247int ginsn_data_end (const symbolS *label);
248const symbolS *ginsn_data_func_symbol (void);
249void ginsn_frob_label (const symbolS *sym);
250
251void frch_ginsn_data_init (const symbolS *func, symbolS *start_addr,
252			   enum ginsn_gen_mode gmode);
253void frch_ginsn_data_cleanup (void);
254int frch_ginsn_data_append (ginsnS *ginsn);
255enum ginsn_gen_mode frch_ginsn_gen_mode (void);
256
257void label_ginsn_map_insert (const symbolS *label, ginsnS *ginsn);
258ginsnS *label_ginsn_map_find (const symbolS *label);
259
260ginsnS *ginsn_new_symbol_func_begin (const symbolS *sym);
261ginsnS *ginsn_new_symbol_func_end (const symbolS *sym);
262ginsnS *ginsn_new_symbol_user_label (const symbolS *sym);
263
264ginsnS *ginsn_new_phantom (const symbolS *sym);
265ginsnS *ginsn_new_symbol (const symbolS *sym, bool real_p);
266ginsnS *ginsn_new_add (const symbolS *sym, bool real_p,
267		       enum ginsn_src_type src1_type, unsigned int src1_reg, offsetT src1_disp,
268		       enum ginsn_src_type src2_type, unsigned int src2_reg, offsetT src2_disp,
269		       enum ginsn_dst_type dst_type, unsigned int dst_reg, offsetT dst_disp);
270ginsnS *ginsn_new_and (const symbolS *sym, bool real_p,
271		       enum ginsn_src_type src1_type, unsigned int src1_reg, offsetT src1_disp,
272		       enum ginsn_src_type src2_type, unsigned int src2_reg, offsetT src2_disp,
273		       enum ginsn_dst_type dst_type, unsigned int dst_reg, offsetT dst_disp);
274ginsnS *ginsn_new_call (const symbolS *sym, bool real_p,
275			enum ginsn_src_type src_type, unsigned int src_reg,
276			const symbolS *src_text_sym);
277ginsnS *ginsn_new_jump (const symbolS *sym, bool real_p,
278			enum ginsn_src_type src_type, unsigned int src_reg,
279			const symbolS *src_ginsn_sym);
280ginsnS *ginsn_new_jump_cond (const symbolS *sym, bool real_p,
281			     enum ginsn_src_type src_type, unsigned int src_reg,
282			     const symbolS *src_ginsn_sym);
283ginsnS *ginsn_new_mov (const symbolS *sym, bool real_p,
284		       enum ginsn_src_type src_type, unsigned int src_reg, offsetT src_disp,
285		       enum ginsn_dst_type dst_type, unsigned int dst_reg, offsetT dst_disp);
286ginsnS *ginsn_new_store (const symbolS *sym, bool real_p,
287			 enum ginsn_src_type src_type, unsigned int src_reg,
288			 enum ginsn_dst_type dst_type, unsigned int dst_reg, offsetT dst_disp);
289ginsnS *ginsn_new_load (const symbolS *sym, bool real_p,
290			enum ginsn_src_type src_type, unsigned int src_reg, offsetT src_disp,
291			enum ginsn_dst_type dst_type, unsigned int dst_reg);
292ginsnS *ginsn_new_sub (const symbolS *sym, bool real_p,
293		       enum ginsn_src_type src1_type, unsigned int src1_reg, offsetT src1_disp,
294		       enum ginsn_src_type src2_type, unsigned int src2_reg, offsetT src2_disp,
295		       enum ginsn_dst_type dst_type, unsigned int dst_reg, offsetT dst_disp);
296ginsnS *ginsn_new_other (const symbolS *sym, bool real_p,
297			 enum ginsn_src_type src1_type, unsigned int src1_val,
298			 enum ginsn_src_type src2_type, unsigned int src2_val,
299			 enum ginsn_dst_type dst_type, unsigned int dst_reg);
300ginsnS *ginsn_new_return (const symbolS *sym, bool real_p);
301
302void ginsn_set_where (ginsnS *ginsn);
303
304bool ginsn_track_reg_p (unsigned int dw2reg, enum ginsn_gen_mode);
305
306int ginsn_link_next (ginsnS *ginsn, ginsnS *next);
307
308enum gcfg_err_code
309{
310  GCFG_OK = 0,
311  GCFG_JLABEL_NOT_PRESENT = 1, /* Warning-level code.  */
312};
313
314typedef struct gbb gbbS;
315typedef struct gedge gedgeS;
316
317/* GBB - Basic block of generic GAS instructions.  */
318
319struct gbb
320{
321  ginsnS *first_ginsn;
322  ginsnS *last_ginsn;
323  uint64_t num_ginsns;
324
325  /* Identifier (linearly increasing natural number) for each gbb.  Added for
326     debugging purpose only.  */
327  uint64_t id;
328
329  bool visited;
330
331  uint32_t num_out_gedges;
332  gedgeS *out_gedges;
333
334  /* Members for SCFI purposes.  */
335  /* SCFI state at the entry of basic block.  */
336  scfi_stateS *entry_state;
337  /* SCFI state at the exit of basic block.  */
338  scfi_stateS *exit_state;
339
340  /* A linked list.  In order of addition.  */
341  gbbS *next;
342};
343
344struct gedge
345{
346  gbbS *dst_bb;
347  /* A linked list.  In order of addition.  */
348  gedgeS *next;
349  bool visited;
350};
351
352/* Control flow graph of generic GAS instructions.  */
353
354struct gcfg
355{
356  uint64_t num_gbbs;
357  gbbS *root_bb;
358};
359
360typedef struct gcfg gcfgS;
361
362#define bb_for_each_insn(bb, ginsn)  \
363  for (ginsn = bb->first_ginsn; ginsn; \
364       ginsn = (ginsn != bb->last_ginsn) ? ginsn->next : NULL)
365
366#define bb_for_each_edge(bb, edge) \
367  for (edge = (edge == NULL) ? bb->out_gedges : edge; edge; edge = edge->next)
368
369#define cfg_for_each_bb(cfg, bb) \
370  for (bb = cfg->root_bb; bb; bb = bb->next)
371
372#define bb_get_first_ginsn(bb)	  \
373  (bb->first_ginsn)
374
375#define bb_get_last_ginsn(bb)	  \
376  (bb->last_ginsn)
377
378gcfgS *gcfg_build (const symbolS *func, int *errp);
379void gcfg_cleanup (gcfgS **gcfg);
380void gcfg_print (const gcfgS *gcfg, FILE *outfile);
381gbbS *gcfg_get_rootbb (gcfgS *gcfg);
382void gcfg_get_bbs_in_prog_order (gcfgS *gcfg, gbbS **prog_order_bbs);
383
384#endif /* GINSN_H.  */
385