Line data Source code
1 : /* gospec.cc -- Specific flags and argument handling of the gcc Go front end.
2 : Copyright (C) 2009-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "tm.h"
24 : #include "opts.h"
25 :
26 : /* This bit is set if we saw a `-xfoo' language specification. */
27 : #define LANGSPEC (1<<1)
28 : /* This bit is set if they did `-lm' or `-lmath'. */
29 : #define MATHLIB (1<<2)
30 : /* This bit is set if they did `-lpthread'. */
31 : #define THREADLIB (1<<3)
32 : /* This bit is set if they did `-lc'. */
33 : #define WITHLIBC (1<<4)
34 : /* Skip this option. */
35 : #define SKIPOPT (1<<5)
36 :
37 : #ifndef MATH_LIBRARY
38 : #define MATH_LIBRARY "m"
39 : #endif
40 : #ifndef MATH_LIBRARY_PROFILE
41 : #define MATH_LIBRARY_PROFILE MATH_LIBRARY
42 : #endif
43 :
44 : #define THREAD_LIBRARY "pthread"
45 : #define THREAD_LIBRARY_PROFILE THREAD_LIBRARY
46 :
47 : #define LIBGO "go"
48 : #define LIBGO_PROFILE LIBGO
49 : #define LIBGOBEGIN "gobegin"
50 :
51 : void
52 7346 : lang_specific_driver (struct cl_decoded_option **in_decoded_options,
53 : unsigned int *in_decoded_options_count,
54 : int *in_added_libraries)
55 : {
56 7346 : unsigned int i, j;
57 :
58 : /* If true, the user gave us the `-p' or `-pg' flag. */
59 7346 : bool saw_profile_flag = false;
60 :
61 : /* This is a tristate:
62 : -1 means we should not link in libgo
63 : 0 means we should link in libgo if it is needed
64 : 1 means libgo is needed and should be linked in.
65 : 2 means libgo is needed and should be linked statically. */
66 7346 : int library = 0;
67 :
68 : /* The new argument list will be contained in this. */
69 7346 : struct cl_decoded_option *new_decoded_options;
70 :
71 : /* "-lm" or "-lmath" if it appears on the command line. */
72 7346 : const struct cl_decoded_option *saw_math = 0;
73 :
74 : /* "-lpthread" if it appears on the command line. */
75 7346 : const struct cl_decoded_option *saw_thread = 0;
76 :
77 : /* "-lc" if it appears on the command line. */
78 7346 : const struct cl_decoded_option *saw_libc = 0;
79 :
80 : /* An array used to flag each argument that needs a bit set for
81 : LANGSPEC, MATHLIB, or WITHLIBC. */
82 7346 : int *args;
83 :
84 : /* Whether we need the thread library. */
85 7346 : int need_thread = 0;
86 :
87 : /* By default, we throw on the math library if we have one. */
88 7346 : int need_math = (MATH_LIBRARY[0] != '\0');
89 :
90 : /* True if we saw -static. */
91 7346 : int static_link = 0;
92 :
93 : /* True if we should add -shared-libgcc to the command-line. */
94 7346 : int shared_libgcc = 1;
95 :
96 : /* The total number of arguments with the new stuff. */
97 7346 : unsigned int argc;
98 :
99 : /* The argument list. */
100 7346 : struct cl_decoded_option *decoded_options;
101 :
102 : /* The number of libraries added in. */
103 7346 : int added_libraries;
104 :
105 : /* The total number of arguments with the new stuff. */
106 7346 : int num_args = 1;
107 :
108 : /* Supports split stack */
109 7346 : int supports_split_stack = 0;
110 :
111 : /* Whether the -o option was used. */
112 7346 : bool saw_opt_o = false;
113 :
114 : /* Whether the -c option was used. Also used for -E, -fsyntax-only,
115 : in general anything which implies only compilation and not
116 : linking. */
117 7346 : bool saw_opt_c = false;
118 :
119 : /* Whether the -S option was used. */
120 7346 : bool saw_opt_S = false;
121 :
122 : #ifdef TARGET_CAN_SPLIT_STACK_64BIT
123 : /* Whether the -m64 option is in force. */
124 : bool is_m64 = TARGET_CAN_SPLIT_STACK_64BIT;
125 : #endif
126 :
127 : /* The first input file with an extension of .go. */
128 7346 : const char *first_go_file = NULL;
129 :
130 : /* Whether we saw any -g option. */
131 7346 : bool saw_opt_g = false;
132 :
133 7346 : argc = *in_decoded_options_count;
134 7346 : decoded_options = *in_decoded_options;
135 7346 : added_libraries = *in_added_libraries;
136 :
137 7346 : args = XCNEWVEC (int, argc);
138 :
139 131628 : for (i = 1; i < argc; i++)
140 : {
141 124282 : const char *arg = decoded_options[i].arg;
142 :
143 124282 : switch (decoded_options[i].opt_index)
144 : {
145 : case OPT_r:
146 : case OPT_nostdlib:
147 : case OPT_nodefaultlibs:
148 124282 : library = -1;
149 : break;
150 :
151 1775 : case OPT_l:
152 1775 : if (strcmp (arg, MATH_LIBRARY) == 0)
153 : {
154 1367 : args[i] |= MATHLIB;
155 1367 : need_math = 0;
156 : }
157 408 : else if (strcmp (arg, THREAD_LIBRARY) == 0)
158 392 : args[i] |= THREADLIB;
159 16 : else if (strcmp (arg, "c") == 0)
160 0 : args[i] |= WITHLIBC;
161 : else
162 : /* Unrecognized libraries (e.g. -lfoo) may require libgo. */
163 16 : library = (library == 0) ? 1 : library;
164 : break;
165 :
166 : #ifdef TARGET_CAN_SPLIT_STACK_64BIT
167 : case OPT_m32:
168 : is_m64 = false;
169 : break;
170 :
171 : case OPT_m64:
172 : is_m64 = true;
173 : break;
174 : #endif
175 :
176 : case OPT_pg:
177 : case OPT_p:
178 124282 : saw_profile_flag = true;
179 : break;
180 :
181 1357 : case OPT_x:
182 1357 : if (library == 0 && strcmp (arg, "go") == 0)
183 481 : library = 1;
184 : break;
185 :
186 713 : case OPT_Xlinker:
187 713 : case OPT_Wl_:
188 : /* Arguments that go directly to the linker might be .o files,
189 : or something, and so might cause libgo to be needed. */
190 713 : if (library == 0)
191 481 : library = 1;
192 : break;
193 :
194 4186 : case OPT_c:
195 4186 : case OPT_E:
196 4186 : case OPT_M:
197 4186 : case OPT_MM:
198 4186 : case OPT_fsyntax_only:
199 : /* Don't specify libraries if we won't link, since that would
200 : cause a warning. */
201 4186 : saw_opt_c = true;
202 4186 : library = -1;
203 4186 : break;
204 :
205 879 : case OPT_S:
206 879 : saw_opt_S = true;
207 879 : library = -1;
208 879 : break;
209 :
210 5142 : case OPT_o:
211 5142 : saw_opt_o = true;
212 5142 : break;
213 :
214 7327 : case OPT_g:
215 7327 : case OPT_gdwarf:
216 7327 : case OPT_gdwarf_:
217 7327 : case OPT_ggdb:
218 7327 : case OPT_gvms:
219 7327 : saw_opt_g = true;
220 7327 : break;
221 :
222 6 : case OPT_static:
223 6 : static_link = 1;
224 6 : break;
225 :
226 6 : case OPT_static_libgcc:
227 6 : shared_libgcc = 0;
228 6 : break;
229 :
230 6 : case OPT_static_libgo:
231 6 : library = library >= 0 ? 2 : library;
232 6 : args[i] |= SKIPOPT;
233 6 : break;
234 :
235 15685 : case OPT_SPECIAL_input_file:
236 15685 : if (library == 0)
237 1831 : library = 1;
238 :
239 15685 : if (first_go_file == NULL)
240 : {
241 7562 : int len;
242 :
243 7562 : len = strlen (arg);
244 7562 : if (len > 3 && strcmp (arg + len - 3, ".go") == 0)
245 124282 : first_go_file = arg;
246 : }
247 :
248 : break;
249 : }
250 : }
251 :
252 : /* There's no point adding -shared-libgcc if we don't have a shared
253 : libgcc. */
254 : #ifndef ENABLE_SHARED_LIBGCC
255 : shared_libgcc = 0;
256 : #endif
257 :
258 : /* Make sure to have room for the trailing NULL argument. */
259 7346 : num_args = argc + need_math + shared_libgcc + (library > 0) * 5 + 10;
260 7346 : new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
261 :
262 7346 : i = 0;
263 7346 : j = 0;
264 :
265 : /* Copy the 0th argument, i.e., the name of the program itself. */
266 7346 : new_decoded_options[j++] = decoded_options[i++];
267 :
268 : #ifdef TARGET_CAN_SPLIT_STACK
269 7346 : supports_split_stack = 1;
270 : #endif
271 :
272 : #ifdef TARGET_CAN_SPLIT_STACK_64BIT
273 : if (is_m64)
274 : supports_split_stack = 1;
275 : #endif
276 :
277 : /* If we are linking, pass -fsplit-stack if it is supported. */
278 7346 : if ((library >= 0) && supports_split_stack)
279 : {
280 2267 : generate_option (OPT_fsplit_stack, NULL, 1, CL_DRIVER,
281 : &new_decoded_options[j]);
282 2267 : j++;
283 : }
284 :
285 : /* The go1 compiler is going to enable debug info by default. If we
286 : don't see any -g options, force -g, so that we invoke the
287 : assembler with the right debug option. */
288 7346 : if (!saw_opt_g)
289 : {
290 1447 : generate_option (OPT_g, "1", 0, CL_DRIVER, &new_decoded_options[j]);
291 1447 : j++;
292 : }
293 :
294 : /* NOTE: We start at 1 now, not 0. */
295 131628 : while (i < argc)
296 : {
297 124282 : new_decoded_options[j] = decoded_options[i];
298 :
299 : /* Make sure -lgo is before the math library, since libgo itself
300 : uses those math routines. */
301 124282 : if (!saw_math && (args[i] & MATHLIB) && library > 0)
302 : {
303 1366 : --j;
304 1366 : saw_math = &decoded_options[i];
305 : }
306 :
307 124282 : if (!saw_thread && (args[i] & THREADLIB) && library > 0)
308 : {
309 392 : --j;
310 392 : saw_thread = &decoded_options[i];
311 : }
312 :
313 124282 : if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
314 : {
315 0 : --j;
316 0 : saw_libc = &decoded_options[i];
317 : }
318 :
319 124282 : if ((args[i] & SKIPOPT) != 0)
320 6 : --j;
321 :
322 124282 : i++;
323 124282 : j++;
324 : }
325 :
326 : /* If we didn't see a -o option, add one. This is because we need
327 : the driver to pass all .go files to go1. Without a -o option the
328 : driver will invoke go1 separately for each input file. FIXME:
329 : This should probably use some other interface to force the driver
330 : to set combine_inputs. */
331 7346 : if (first_go_file != NULL && !saw_opt_o)
332 : {
333 395 : if (saw_opt_c || saw_opt_S)
334 : {
335 395 : const char *base;
336 395 : int baselen;
337 395 : int alen;
338 395 : char *out;
339 :
340 395 : base = lbasename (first_go_file);
341 395 : baselen = strlen (base) - 3;
342 395 : alen = baselen + 3;
343 395 : out = XNEWVEC (char, alen);
344 395 : memcpy (out, base, baselen);
345 : /* The driver will convert .o to some other suffix (e.g.,
346 : .obj) if appropriate. */
347 395 : out[baselen] = '.';
348 395 : if (saw_opt_S)
349 0 : out[baselen + 1] = 's';
350 : else
351 395 : out[baselen + 1] = 'o';
352 395 : out[baselen + 2] = '\0';
353 395 : generate_option (OPT_o, out, 1, CL_DRIVER,
354 395 : &new_decoded_options[j]);
355 : }
356 : else
357 0 : generate_option (OPT_o, "a.out", 1, CL_DRIVER,
358 0 : &new_decoded_options[j]);
359 395 : j++;
360 : }
361 :
362 : /* Add `-lgo' if we haven't already done so. */
363 7346 : if (library > 0)
364 : {
365 1494 : generate_option (OPT_l, LIBGOBEGIN, 1, CL_DRIVER,
366 1494 : &new_decoded_options[j]);
367 1494 : added_libraries++;
368 1494 : j++;
369 :
370 : #ifdef HAVE_LD_STATIC_DYNAMIC
371 1494 : if (library > 1 && !static_link)
372 : {
373 2 : generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
374 2 : &new_decoded_options[j]);
375 2 : j++;
376 : }
377 : #endif
378 :
379 1494 : generate_option (OPT_l, saw_profile_flag ? LIBGO_PROFILE : LIBGO, 1,
380 1494 : CL_DRIVER, &new_decoded_options[j]);
381 1494 : added_libraries++;
382 1494 : j++;
383 :
384 : #ifdef HAVE_LD_STATIC_DYNAMIC
385 1494 : if (library > 1 && !static_link)
386 : {
387 2 : generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
388 2 : &new_decoded_options[j]);
389 2 : j++;
390 : }
391 : #endif
392 :
393 : /* When linking libgo statically we also need to link with the
394 : pthread library. */
395 1494 : if (library > 1 || static_link)
396 5 : need_thread = 1;
397 : }
398 :
399 7346 : if (saw_thread)
400 392 : new_decoded_options[j++] = *saw_thread;
401 6954 : else if (library > 0 && need_thread)
402 : {
403 2 : generate_option (OPT_l,
404 : (saw_profile_flag
405 : ? THREAD_LIBRARY_PROFILE
406 : : THREAD_LIBRARY),
407 2 : 1, CL_DRIVER, &new_decoded_options[j]);
408 2 : added_libraries++;
409 2 : j++;
410 : }
411 :
412 7346 : if (saw_math)
413 1366 : new_decoded_options[j++] = *saw_math;
414 5980 : else if (library > 0 && need_math)
415 : {
416 128 : generate_option (OPT_l,
417 : saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY,
418 128 : 1, CL_DRIVER, &new_decoded_options[j]);
419 128 : added_libraries++;
420 128 : j++;
421 : }
422 :
423 7346 : if (saw_libc)
424 0 : new_decoded_options[j++] = *saw_libc;
425 7346 : if (shared_libgcc && !static_link)
426 7334 : generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
427 7334 : &new_decoded_options[j++]);
428 :
429 : /* libgcc wraps pthread_create to support split stack, however, due to
430 : relative ordering of -lpthread and -lgcc, we can't just mark
431 : __real_pthread_create in libgcc as non-weak. But we need to link in
432 : pthread_create from pthread if we are statically linking, so we work-
433 : around by passing -u pthread_create to the linker. */
434 7346 : if (static_link && supports_split_stack)
435 : {
436 6 : generate_option (OPT_Wl_, "-u,pthread_create", 1, CL_DRIVER,
437 6 : &new_decoded_options[j]);
438 6 : j++;
439 : }
440 :
441 : #if defined(TARGET_SOLARIS) && !HAVE_GNU_LD
442 : /* We use a common symbol for go$zerovalue. On Solaris, when not
443 : using the GNU linker, the Solaris linker needs an option to not
444 : warn about this. Everything works without this option, but you
445 : get unsightly warnings at link time. */
446 : if (library > 0)
447 : {
448 : generate_option (OPT_Wl_, "-t", 1, CL_DRIVER, &new_decoded_options[j]);
449 : j++;
450 : }
451 : #endif
452 :
453 7346 : *in_decoded_options_count = j;
454 7346 : *in_decoded_options = new_decoded_options;
455 7346 : *in_added_libraries = added_libraries;
456 7346 : }
457 :
458 : /* Called before linking. Returns 0 on success and -1 on failure. */
459 6116 : int lang_specific_pre_link (void) /* Not used for Go. */
460 : {
461 6116 : return 0;
462 : }
463 :
464 : /* Number of extra output files that lang_specific_pre_link may generate. */
465 : int lang_specific_extra_outfiles = 0; /* Not used for Go. */
|