https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86517

--- Comment #7 from Jan Hubicka <hubicka at ucw dot cz> ---
Hi,
I am attaching patch I am testing and also table generated by a script that
walks through individual combinations of options.  The combination rules are as
follows.

I tried to take into account that targets may default to some form of PIC or
PIE. That is why, for example combining -fpic and empty options results in
empty options and no no-pic.

Note that in addition to lto-wrapper option merging we now have logic that
disables PIC/PIE when final binary is built based on lto-plugion output (it
knows if it builds binary, relocatable binary, library or incrementally links).
Still we rely on the merging to choose particular form of PIC/PIE and we need
it right in incremental link where linker does not help us.

   -fpic +    -fpic =>  -fpic 
   -fpic +    -fPIC =>  -fpic 
   -fpic +    -fpie =>  -fpie 
   -fpic +    -fPIE =>  -fpie 
   -fpic + -fno-pic =>  -fno-pic 
   -fpic + -fno-pie =>  
   -fpic +          =>  
   -fPIC +    -fpic =>  -fpic 
   -fPIC +    -fPIC =>  -fPIC 
   -fPIC +    -fpie =>  -fpie 
   -fPIC +    -fPIE =>  -fPIE 
   -fPIC + -fno-pic =>  -fno-pic 
   -fPIC + -fno-pie =>  
   -fPIC +          =>  
   -fpie +    -fpic =>  -fpie 
   -fpie +    -fPIC =>  -fpie 
   -fpie +    -fpie =>  -fpie 
   -fpie +    -fPIE =>  -fpie 
   -fpie + -fno-pic =>  
   -fpie + -fno-pie =>  
   -fpie +          =>  
   -fPIE +    -fpic =>  -fpie 
   -fPIE +    -fPIC =>  -fPIE 
   -fPIE +    -fpie =>  -fpie 
   -fPIE +    -fPIE =>  -fPIE 
   -fPIE + -fno-pic =>  
   -fPIE + -fno-pie =>  
   -fPIE +          =>  
-fno-pic +    -fpic =>  -fno-pic 
-fno-pic +    -fPIC =>  -fno-pic 
-fno-pic +    -fpie =>  -fno-pic 
-fno-pic +    -fPIE =>  -fno-pic 
-fno-pic + -fno-pic =>  -fno-pic 
-fno-pic + -fno-pie =>  -fno-pic 
-fno-pic +          =>  -fno-pic 
-fno-pie +    -fpic =>  -fno-pie 
-fno-pie +    -fPIC =>  -fno-pie 
-fno-pie +    -fpie =>  -fno-pie 
-fno-pie +    -fPIE =>  -fno-pie 
-fno-pie + -fno-pic =>  -fno-pie 
-fno-pie + -fno-pie =>  -fno-pie 
-fno-pie +          =>  -fno-pie 
   -fpic +          =>  
   -fPIC +          =>  
   -fpie +          =>  
   -fPIE +          =>  
-fno-pic +          =>  
-fno-pie +          =>  
         +          =>  
Index: lto-wrapper.c
===================================================================
--- lto-wrapper.c       (revision 262682)
+++ lto-wrapper.c       (working copy)
@@ -408,6 +408,11 @@ merge_and_complain (struct cl_decoded_op
      It is a common mistake to mix few -fPIC compiled objects into otherwise
      non-PIC code.  We do not want to build everything with PIC then.

+     Similarly we merge PIE options, however in addition we keep
+      -fPIC + -fPIE = -fPIE
+      -fpic + -fPIE = -fpie
+      -fPIC/-fpic + -fpie = -fpie
+
      It would be good to warn on mismatches, but it is bit hard to do as
      we do not know what nothing translates to.  */

@@ -415,11 +420,34 @@ merge_and_complain (struct cl_decoded_op
     if ((*decoded_options)[j].opt_index == OPT_fPIC
         || (*decoded_options)[j].opt_index == OPT_fpic)
       {
-       if (!pic_option
-           || (pic_option->value > 0) != ((*decoded_options)[j].value > 0))
-         remove_option (decoded_options, j, decoded_options_count);
-       else if (pic_option->opt_index == OPT_fPIC
-                && (*decoded_options)[j].opt_index == OPT_fpic)
+       /* -fno-pic in one unit implies -fno-pic everywhere.  */
+       if ((*decoded_options)[j].value == 0)
+         j++;
+       /* If we have no pic option or merge in -fno-pic, we still may turn
+          existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
+       else if ((pic_option && pic_option->value == 0)
+                || !pic_option)
+         {
+           if (pie_option && pie_option->value > 0)
+             {
+               bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+                          && pie_option->opt_index == OPT_fPIE;
+               (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+               (*decoded_options)[j].canonical_option[0] = big ? "-fPIE" :
"-fpie";
+               j++;
+             }
+           else if (pic_option)
+             {
+               (*decoded_options)[j] = *pic_option;
+               j++;
+             }
+           /* We do not know if target defaults to pic or not, so just remove
+              option if it is missing in one unit but enabled in other.  */
+           else
+             remove_option (decoded_options, j, decoded_options_count);
+         }
+       else if (pic_option->opt_index == OPT_fpic
+                && (*decoded_options)[j].opt_index == OPT_fPIC)
          {
            (*decoded_options)[j] = *pic_option;
            j++;
@@ -430,11 +458,37 @@ merge_and_complain (struct cl_decoded_op
    else if ((*decoded_options)[j].opt_index == OPT_fPIE
             || (*decoded_options)[j].opt_index == OPT_fpie)
       {
-       if (!pie_option
-           || pie_option->value != (*decoded_options)[j].value)
-         remove_option (decoded_options, j, decoded_options_count);
-       else if (pie_option->opt_index == OPT_fPIE
-                && (*decoded_options)[j].opt_index == OPT_fpie)
+       /* -fno-pie in one unit implies -fno-pie everywhere.  */
+       if ((*decoded_options)[j].value == 0)
+         j++;
+       /* If we have no pie option or merge in -fno-pie, we still preserve
+          PIE/pie if pic/PIC is present.  */
+       else if ((pie_option && pie_option->value == 0)
+                || !pie_option)
+         {
+           /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie.  */
+           if (pic_option && pic_option->value > 0)
+             {
+               if (pic_option->opt_index == OPT_fpic
+                   && (*decoded_options)[j].opt_index == OPT_fPIE)
+                 {
+                   (*decoded_options)[j].opt_index = OPT_fpie;
+                   (*decoded_options)[j].canonical_option[0] = "-fpie";
+                 }
+               j++;
+             }
+           /* Target may default to pic.  */
+           else if (pie_option && pic_option)
+             {
+               (*decoded_options)[j] = *pie_option;
+               j++;
+             }
+           /* Target may default to pie.  */
+           else
+             remove_option (decoded_options, j, decoded_options_count);
+         }
+       else if (pie_option->opt_index == OPT_fpie
+                && (*decoded_options)[j].opt_index == OPT_fPIE)
          {
            (*decoded_options)[j] = *pie_option;
            j++;

Reply via email to