1 | /* LTO IL options. |
2 | |
3 | Copyright (C) 2009-2023 Free Software Foundation, Inc. |
4 | Contributed by Simon Baldwin <simonb@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 "target.h" |
27 | #include "tree.h" |
28 | #include "gimple.h" |
29 | #include "cgraph.h" |
30 | #include "lto-streamer.h" |
31 | #include "opts.h" |
32 | #include "toplev.h" |
33 | |
34 | /* Append the option piece OPT to the COLLECT_GCC_OPTIONS string |
35 | set up by OB, appropriately quoted and separated by spaces |
36 | (if !*FIRST_P). */ |
37 | |
38 | static void |
39 | append_to_collect_gcc_options (struct obstack *ob, |
40 | bool *first_p, const char *opt) |
41 | { |
42 | const char *p, *q = opt; |
43 | if (!*first_p) |
44 | obstack_grow (ob, " " , 1); |
45 | obstack_grow (ob, "'" , 1); |
46 | while ((p = strchr (s: q, c: '\''))) |
47 | { |
48 | obstack_grow (ob, q, p - q); |
49 | obstack_grow (ob, "'\\''" , 4); |
50 | q = ++p; |
51 | } |
52 | obstack_grow (ob, q, strlen (q)); |
53 | obstack_grow (ob, "'" , 1); |
54 | *first_p = false; |
55 | } |
56 | |
57 | /* Write currently held options to an LTO IL section. */ |
58 | |
59 | void |
60 | lto_write_options (void) |
61 | { |
62 | char *section_name; |
63 | struct obstack temporary_obstack; |
64 | unsigned int i, j; |
65 | char *args; |
66 | bool first_p = true; |
67 | |
68 | section_name = lto_get_section_name (LTO_section_opts, NULL, 0, NULL); |
69 | lto_begin_section (section_name, false); |
70 | |
71 | obstack_init (&temporary_obstack); |
72 | |
73 | if (!OPTION_SET_P (flag_openmp) |
74 | && !global_options.x_flag_openmp) |
75 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, |
76 | opt: "-fno-openmp" ); |
77 | if (!OPTION_SET_P (flag_openacc) |
78 | && !global_options.x_flag_openacc) |
79 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, |
80 | opt: "-fno-openacc" ); |
81 | /* Append PIC/PIE mode because its default depends on target and it is |
82 | subject of merging in lto-wrapper. */ |
83 | if (!OPTION_SET_P (flag_pic) && !OPTION_SET_P (flag_pie)) |
84 | { |
85 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, |
86 | opt: global_options.x_flag_pic == 2 |
87 | ? "-fPIC" |
88 | : global_options.x_flag_pic == 1 |
89 | ? "-fpic" |
90 | : global_options.x_flag_pie == 2 |
91 | ? "-fPIE" |
92 | : global_options.x_flag_pie == 1 |
93 | ? "-fpie" |
94 | : "-fno-pie" ); |
95 | } |
96 | |
97 | if (!OPTION_SET_P (flag_cf_protection)) |
98 | { |
99 | append_to_collect_gcc_options ( |
100 | ob: &temporary_obstack, first_p: &first_p, |
101 | opt: global_options.x_flag_cf_protection == CF_NONE |
102 | ? "-fcf-protection=none" |
103 | : global_options.x_flag_cf_protection == CF_FULL |
104 | ? "-fcf-protection=full" |
105 | : global_options.x_flag_cf_protection == CF_BRANCH |
106 | ? "-fcf-protection=branch" |
107 | : global_options.x_flag_cf_protection == CF_RETURN |
108 | ? "-fcf-protection=return" |
109 | : "" ); |
110 | } |
111 | |
112 | /* If debug info is enabled append -g. */ |
113 | if (debug_info_level > DINFO_LEVEL_NONE) |
114 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, opt: "-g" ); |
115 | |
116 | /* Append options from target hook and store them to offload_lto section. */ |
117 | if (lto_stream_offload_p) |
118 | { |
119 | char *offload_opts = targetm.offload_options (); |
120 | char *offload_ptr = offload_opts; |
121 | while (offload_ptr) |
122 | { |
123 | char *next = strchr (s: offload_ptr, c: ' '); |
124 | if (next) |
125 | *next++ = '\0'; |
126 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, |
127 | opt: offload_ptr); |
128 | offload_ptr = next; |
129 | } |
130 | free (ptr: offload_opts); |
131 | } |
132 | |
133 | /* Output explicitly passed options. */ |
134 | for (i = 1; i < save_decoded_options_count; ++i) |
135 | { |
136 | struct cl_decoded_option *option = &save_decoded_options[i]; |
137 | |
138 | /* Skip explicitly some common options that we do not need. */ |
139 | switch (option->opt_index) |
140 | { |
141 | case OPT_dumpbase: |
142 | case OPT_SPECIAL_unknown: |
143 | case OPT_SPECIAL_ignore: |
144 | case OPT_SPECIAL_warn_removed: |
145 | case OPT_SPECIAL_program_name: |
146 | case OPT_SPECIAL_input_file: |
147 | case OPT_dumpdir: |
148 | case OPT_fresolution_: |
149 | case OPT_fdebug_prefix_map_: |
150 | case OPT_ffile_prefix_map_: |
151 | case OPT_fmacro_prefix_map_: |
152 | case OPT_fprofile_prefix_map_: |
153 | case OPT_fcanon_prefix_map: |
154 | case OPT_fwhole_program: |
155 | continue; |
156 | |
157 | default: |
158 | break; |
159 | } |
160 | |
161 | /* Skip frontend and driver specific options here. */ |
162 | if (!(cl_options[option->opt_index].flags & (CL_COMMON|CL_TARGET|CL_LTO))) |
163 | continue; |
164 | |
165 | /* Do not store target-specific options in offload_lto section. */ |
166 | if ((cl_options[option->opt_index].flags & CL_TARGET) |
167 | && lto_stream_offload_p) |
168 | continue; |
169 | |
170 | /* Drop options created from the gcc driver that will be rejected |
171 | when passed on to the driver again. */ |
172 | if (cl_options[option->opt_index].cl_reject_driver) |
173 | continue; |
174 | |
175 | /* Also drop all options that are handled by the driver as well, |
176 | which includes things like -o and -v or -fhelp for example. |
177 | We do not need those. The only exception is -foffload option, if we |
178 | write it in offload_lto section. Also drop all diagnostic options. */ |
179 | if ((cl_options[option->opt_index].flags & (CL_DRIVER|CL_WARNING)) |
180 | && (!lto_stream_offload_p |
181 | || option->opt_index != OPT_foffload_options_)) |
182 | continue; |
183 | |
184 | for (j = 0; j < option->canonical_option_num_elements; ++j) |
185 | append_to_collect_gcc_options (ob: &temporary_obstack, first_p: &first_p, |
186 | opt: option->canonical_option[j]); |
187 | } |
188 | |
189 | const char *collect_as_options = getenv (name: "COLLECT_AS_OPTIONS" ); |
190 | if (collect_as_options) |
191 | prepend_xassembler_to_collect_as_options (collect_as_options, |
192 | &temporary_obstack); |
193 | |
194 | obstack_grow (&temporary_obstack, "\0" , 1); |
195 | args = XOBFINISH (&temporary_obstack, char *); |
196 | lto_write_data (args, strlen (s: args) + 1); |
197 | lto_end_section (); |
198 | |
199 | obstack_free (&temporary_obstack, NULL); |
200 | free (ptr: section_name); |
201 | } |
202 | |