LCOV - code coverage report
Current view: top level - gcc/go - gospec.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.2 % 184 177
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            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.  */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.