1 | /* Routines for emitting GIMPLE to a file stream. |
2 | |
3 | Copyright (C) 2011-2023 Free Software Foundation, Inc. |
4 | Contributed by Diego Novillo <dnovillo@google.com> |
5 | |
6 | This file is part of GCC. |
7 | |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free |
10 | Software Foundation; either version 3, or (at your option) any later |
11 | version. |
12 | |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
16 | for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ |
21 | |
22 | #include "config.h" |
23 | #include "system.h" |
24 | #include "coretypes.h" |
25 | #include "backend.h" |
26 | #include "tree.h" |
27 | #include "gimple.h" |
28 | #include "gimple-ssa.h" |
29 | #include "gimple-streamer.h" |
30 | #include "tree-eh.h" |
31 | #include "gimple-iterator.h" |
32 | #include "cgraph.h" |
33 | #include "value-prof.h" |
34 | #include "gimple-pretty-print.h" |
35 | |
36 | /* Output PHI function PHI to the main stream in OB. */ |
37 | |
38 | static void |
39 | output_phi (struct output_block *ob, gphi *phi) |
40 | { |
41 | unsigned i, len = gimple_phi_num_args (gs: phi); |
42 | |
43 | streamer_write_record_start (ob, tag: lto_gimple_code_to_tag (code: GIMPLE_PHI)); |
44 | streamer_write_uhwi (ob, SSA_NAME_VERSION (PHI_RESULT (phi))); |
45 | |
46 | for (i = 0; i < len; i++) |
47 | { |
48 | stream_write_tree (ob, gimple_phi_arg_def (phi, i), true); |
49 | streamer_write_uhwi (ob, gimple_phi_arg_edge (phi, i)->src->index); |
50 | bitpack_d bp = bitpack_create (s: ob->main_stream); |
51 | location_t loc = gimple_phi_arg_location (phi, i); |
52 | stream_output_location_and_block (ob, &bp, loc); |
53 | } |
54 | } |
55 | |
56 | |
57 | /* Emit statement STMT on the main stream of output block OB. */ |
58 | |
59 | static void |
60 | output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt) |
61 | { |
62 | unsigned i; |
63 | enum gimple_code code; |
64 | enum LTO_tags tag; |
65 | struct bitpack_d bp; |
66 | histogram_value hist; |
67 | |
68 | /* Emit identifying tag. */ |
69 | code = gimple_code (g: stmt); |
70 | tag = lto_gimple_code_to_tag (code); |
71 | streamer_write_record_start (ob, tag); |
72 | |
73 | /* Emit the tuple header. */ |
74 | bp = bitpack_create (s: ob->main_stream); |
75 | bp_pack_var_len_unsigned (&bp, gimple_num_ops (gs: stmt)); |
76 | bp_pack_value (bp: &bp, val: gimple_no_warning_p (stmt), nbits: 1); |
77 | if (is_gimple_assign (gs: stmt)) |
78 | bp_pack_value (bp: &bp, |
79 | val: gimple_assign_nontemporal_move_p ( |
80 | gs: as_a <gassign *> (p: stmt)), |
81 | nbits: 1); |
82 | bp_pack_value (bp: &bp, val: gimple_has_volatile_ops (stmt), nbits: 1); |
83 | hist = gimple_histogram_value (fn, stmt); |
84 | bp_pack_value (bp: &bp, val: hist != NULL, nbits: 1); |
85 | bp_pack_var_len_unsigned (&bp, stmt->subcode); |
86 | |
87 | /* Emit location information for the statement, including gimple_block. */ |
88 | stream_output_location_and_block (ob, &bp, gimple_location (stmt)); |
89 | |
90 | /* Emit the operands. */ |
91 | switch (gimple_code (g: stmt)) |
92 | { |
93 | case GIMPLE_RESX: |
94 | streamer_write_hwi (ob, gimple_resx_region (resx_stmt: as_a <gresx *> (p: stmt))); |
95 | break; |
96 | |
97 | case GIMPLE_EH_MUST_NOT_THROW: |
98 | stream_write_tree (ob, |
99 | gimple_eh_must_not_throw_fndecl ( |
100 | as_a <geh_mnt *> (stmt)), |
101 | true); |
102 | break; |
103 | |
104 | case GIMPLE_EH_DISPATCH: |
105 | streamer_write_hwi (ob, |
106 | gimple_eh_dispatch_region ( |
107 | eh_dispatch_stmt: as_a <geh_dispatch *> (p: stmt))); |
108 | break; |
109 | |
110 | case GIMPLE_ASM: |
111 | { |
112 | gasm *asm_stmt = as_a <gasm *> (p: stmt); |
113 | streamer_write_uhwi (ob, gimple_asm_ninputs (asm_stmt)); |
114 | streamer_write_uhwi (ob, gimple_asm_noutputs (asm_stmt)); |
115 | streamer_write_uhwi (ob, gimple_asm_nclobbers (asm_stmt)); |
116 | streamer_write_uhwi (ob, gimple_asm_nlabels (asm_stmt)); |
117 | streamer_write_string (ob, ob->main_stream, |
118 | gimple_asm_string (asm_stmt), true); |
119 | } |
120 | /* Fallthru */ |
121 | |
122 | case GIMPLE_ASSIGN: |
123 | case GIMPLE_CALL: |
124 | case GIMPLE_RETURN: |
125 | case GIMPLE_SWITCH: |
126 | case GIMPLE_LABEL: |
127 | case GIMPLE_COND: |
128 | case GIMPLE_GOTO: |
129 | case GIMPLE_DEBUG: |
130 | for (i = 0; i < gimple_num_ops (gs: stmt); i++) |
131 | { |
132 | tree op = gimple_op (gs: stmt, i); |
133 | tree *basep = NULL; |
134 | /* Wrap all uses of non-automatic variables inside MEM_REFs |
135 | so that we do not have to deal with type mismatches on |
136 | merged symbols during IL read in. The first operand |
137 | of GIMPLE_DEBUG must be a decl, not MEM_REF, though. */ |
138 | if (!flag_wpa && op && (i || !is_gimple_debug (gs: stmt))) |
139 | { |
140 | basep = &op; |
141 | if (TREE_CODE (*basep) == ADDR_EXPR) |
142 | basep = &TREE_OPERAND (*basep, 0); |
143 | while (handled_component_p (t: *basep)) |
144 | basep = &TREE_OPERAND (*basep, 0); |
145 | if (VAR_P (*basep) |
146 | && !auto_var_in_fn_p (*basep, fn->decl) |
147 | && !DECL_REGISTER (*basep)) |
148 | { |
149 | bool volatilep = TREE_THIS_VOLATILE (*basep); |
150 | tree ptrtype = build_pointer_type (TREE_TYPE (*basep)); |
151 | *basep = build2 (MEM_REF, TREE_TYPE (*basep), |
152 | build1 (ADDR_EXPR, ptrtype, *basep), |
153 | build_int_cst (ptrtype, 0)); |
154 | TREE_THIS_VOLATILE (*basep) = volatilep; |
155 | } |
156 | else |
157 | basep = NULL; |
158 | } |
159 | stream_write_tree (ob, op, true); |
160 | /* Restore the original base if we wrapped it inside a MEM_REF. */ |
161 | if (basep) |
162 | *basep = TREE_OPERAND (TREE_OPERAND (*basep, 0), 0); |
163 | } |
164 | if (is_gimple_call (gs: stmt)) |
165 | { |
166 | if (gimple_call_internal_p (gs: stmt)) |
167 | streamer_write_enum (ob->main_stream, internal_fn, |
168 | IFN_LAST, gimple_call_internal_fn (stmt)); |
169 | else |
170 | stream_write_tree (ob, gimple_call_fntype (stmt), true); |
171 | } |
172 | break; |
173 | |
174 | case GIMPLE_NOP: |
175 | case GIMPLE_PREDICT: |
176 | break; |
177 | |
178 | case GIMPLE_TRANSACTION: |
179 | { |
180 | gtransaction *txn = as_a <gtransaction *> (p: stmt); |
181 | gcc_assert (gimple_transaction_body (txn) == NULL); |
182 | stream_write_tree (ob, gimple_transaction_label_norm (txn), true); |
183 | stream_write_tree (ob, gimple_transaction_label_uninst (txn), true); |
184 | stream_write_tree (ob, gimple_transaction_label_over (txn), true); |
185 | } |
186 | break; |
187 | |
188 | default: |
189 | gcc_unreachable (); |
190 | } |
191 | if (hist) |
192 | stream_out_histogram_value (ob, hist); |
193 | } |
194 | |
195 | |
196 | /* Output a basic block BB to the main stream in OB for this FN. */ |
197 | |
198 | void |
199 | output_bb (struct output_block *ob, basic_block bb, struct function *fn) |
200 | { |
201 | gimple_stmt_iterator bsi = gsi_start_bb (bb); |
202 | |
203 | streamer_write_record_start (ob, |
204 | tag: (!gsi_end_p (i: bsi)) || phi_nodes (bb) |
205 | ? LTO_bb1 |
206 | : LTO_bb0); |
207 | |
208 | streamer_write_uhwi (ob, bb->index); |
209 | bb->count.stream_out (ob); |
210 | streamer_write_hwi (ob, bb->flags); |
211 | |
212 | if (!gsi_end_p (i: bsi) || phi_nodes (bb)) |
213 | { |
214 | /* Output the statements. The list of statements is terminated |
215 | with a zero. */ |
216 | for (bsi = gsi_start_bb (bb); !gsi_end_p (i: bsi); gsi_next (i: &bsi)) |
217 | { |
218 | int region; |
219 | gimple *stmt = gsi_stmt (i: bsi); |
220 | if (streamer_dump_file) |
221 | { |
222 | fprintf (stream: streamer_dump_file, format: " Streaming gimple stmt " ); |
223 | print_gimple_stmt (streamer_dump_file, stmt, 0, TDF_SLIM); |
224 | } |
225 | |
226 | output_gimple_stmt (ob, fn, stmt); |
227 | |
228 | /* Emit the EH region holding STMT. */ |
229 | region = lookup_stmt_eh_lp_fn (fn, stmt); |
230 | if (region != 0) |
231 | { |
232 | streamer_write_record_start (ob, tag: LTO_eh_region); |
233 | streamer_write_hwi (ob, region); |
234 | } |
235 | else |
236 | streamer_write_record_start (ob, tag: LTO_null); |
237 | } |
238 | |
239 | streamer_write_record_start (ob, tag: LTO_null); |
240 | |
241 | for (gphi_iterator psi = gsi_start_phis (bb); |
242 | !gsi_end_p (i: psi); |
243 | gsi_next (i: &psi)) |
244 | { |
245 | gphi *phi = psi.phi (); |
246 | |
247 | /* Only emit PHIs for gimple registers. PHI nodes for .MEM |
248 | will be filled in on reading when the SSA form is |
249 | updated. */ |
250 | if (!virtual_operand_p (op: gimple_phi_result (gs: phi))) |
251 | output_phi (ob, phi); |
252 | } |
253 | |
254 | streamer_write_record_start (ob, tag: LTO_null); |
255 | } |
256 | } |
257 | |