1 /* Common hooks for IBM RS/6000. 2 Copyright (C) 1991-2019 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 7 under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 3, or (at your 9 option) any later version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 License 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 "diagnostic-core.h" 24 #include "tm.h" 25 #include "common/common-target.h" 26 #include "common/common-target-def.h" 27 #include "opts.h" 28 #include "flags.h" 29 #include "params.h" 30 31 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ 32 static const struct default_options rs6000_option_optimization_table[] = 33 { 34 /* Enable -fsched-pressure for first pass instruction scheduling. */ 35 { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, 36 { OPT_LEVELS_NONE, 0, NULL, 0 } 37 }; 38 39 /* Implement TARGET_OPTION_INIT_STRUCT. */ 40 41 static void 42 rs6000_option_init_struct (struct gcc_options *opts) 43 { 44 if (DEFAULT_ABI == ABI_DARWIN) 45 /* The Darwin libraries never set errno, so we might as well 46 avoid calling them when that's the only reason we would. */ 47 opts->x_flag_errno_math = 0; 48 49 /* Enable section anchors by default. */ 50 if (!TARGET_MACHO) 51 opts->x_flag_section_anchors = 1; 52 } 53 54 /* Implement TARGET_OPTION_DEFAULT_PARAMS. */ 55 56 static void 57 rs6000_option_default_params (void) 58 { 59 /* Double growth factor to counter reduced min jump length. */ 60 set_default_param_value (PARAM_MAX_GROW_COPY_BB_INSNS, 16); 61 } 62 63 /* If not otherwise specified by a target, make 'long double' equivalent to 64 'double'. */ 65 66 #ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE 67 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64 68 #endif 69 70 /* Implement TARGET_HANDLE_OPTION. */ 71 72 static bool 73 rs6000_handle_option (struct gcc_options *opts, struct gcc_options *opts_set, 74 const struct cl_decoded_option *decoded, 75 location_t loc) 76 { 77 enum fpu_type_t fpu_type = FPU_NONE; 78 char *p, *q; 79 size_t code = decoded->opt_index; 80 const char *arg = decoded->arg; 81 int value = decoded->value; 82 83 switch (code) 84 { 85 case OPT_mfull_toc: 86 opts->x_rs6000_isa_flags &= ~OPTION_MASK_MINIMAL_TOC; 87 opts->x_TARGET_NO_FP_IN_TOC = 0; 88 opts->x_TARGET_NO_SUM_IN_TOC = 0; 89 opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 90 #ifdef TARGET_USES_SYSV4_OPT 91 /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be 92 just the same as -mminimal-toc. */ 93 opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 94 opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 95 #endif 96 break; 97 98 #ifdef TARGET_USES_SYSV4_OPT 99 case OPT_mtoc: 100 /* Make -mtoc behave like -mminimal-toc. */ 101 opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 102 opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 103 break; 104 #endif 105 106 #ifdef TARGET_USES_AIX64_OPT 107 case OPT_maix64: 108 #else 109 case OPT_m64: 110 #endif 111 opts->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64; 112 opts->x_rs6000_isa_flags |= (~opts_set->x_rs6000_isa_flags 113 & OPTION_MASK_PPC_GFXOPT); 114 opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64; 115 break; 116 117 #ifdef TARGET_USES_AIX64_OPT 118 case OPT_maix32: 119 #else 120 case OPT_m32: 121 #endif 122 opts->x_rs6000_isa_flags &= ~OPTION_MASK_POWERPC64; 123 opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64; 124 break; 125 126 case OPT_mminimal_toc: 127 if (value == 1) 128 { 129 opts->x_TARGET_NO_FP_IN_TOC = 0; 130 opts->x_TARGET_NO_SUM_IN_TOC = 0; 131 } 132 break; 133 134 case OPT_mpowerpc_gpopt: 135 case OPT_mpowerpc_gfxopt: 136 break; 137 138 case OPT_mdebug_: 139 p = ASTRDUP (arg); 140 opts->x_rs6000_debug = 0; 141 142 while ((q = strtok (p, ",")) != NULL) 143 { 144 unsigned mask = 0; 145 bool invert; 146 147 p = NULL; 148 if (*q == '!') 149 { 150 invert = true; 151 q++; 152 } 153 else 154 invert = false; 155 156 if (! strcmp (q, "all")) 157 mask = MASK_DEBUG_ALL; 158 else if (! strcmp (q, "stack")) 159 mask = MASK_DEBUG_STACK; 160 else if (! strcmp (q, "arg")) 161 mask = MASK_DEBUG_ARG; 162 else if (! strcmp (q, "reg")) 163 mask = MASK_DEBUG_REG; 164 else if (! strcmp (q, "addr")) 165 mask = MASK_DEBUG_ADDR; 166 else if (! strcmp (q, "cost")) 167 mask = MASK_DEBUG_COST; 168 else if (! strcmp (q, "target")) 169 mask = MASK_DEBUG_TARGET; 170 else if (! strcmp (q, "builtin")) 171 mask = MASK_DEBUG_BUILTIN; 172 else 173 error_at (loc, "unknown %<-mdebug-%s%> switch", q); 174 175 if (invert) 176 opts->x_rs6000_debug &= ~mask; 177 else 178 opts->x_rs6000_debug |= mask; 179 } 180 break; 181 182 #ifdef TARGET_USES_SYSV4_OPT 183 case OPT_mrelocatable: 184 if (value == 1) 185 { 186 opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 187 opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC; 188 opts->x_TARGET_NO_FP_IN_TOC = 1; 189 } 190 break; 191 192 case OPT_mrelocatable_lib: 193 if (value == 1) 194 { 195 opts->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE 196 | OPTION_MASK_MINIMAL_TOC); 197 opts_set->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE 198 | OPTION_MASK_MINIMAL_TOC); 199 opts->x_TARGET_NO_FP_IN_TOC = 1; 200 } 201 else 202 { 203 opts->x_rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE; 204 opts_set->x_rs6000_isa_flags |= OPTION_MASK_RELOCATABLE; 205 } 206 break; 207 #endif 208 209 case OPT_mabi_altivec: 210 /* Enabling the AltiVec ABI turns off the SPE ABI. */ 211 opts->x_rs6000_spe_abi = 0; 212 break; 213 214 case OPT_mabi_spe: 215 opts->x_rs6000_altivec_abi = 0; 216 break; 217 218 case OPT_mlong_double_: 219 if (value != 64 && value != 128) 220 { 221 error_at (loc, "unknown switch %<-mlong-double-%s%>", arg); 222 opts->x_rs6000_long_double_type_size 223 = RS6000_DEFAULT_LONG_DOUBLE_SIZE; 224 return false; 225 } 226 break; 227 228 case OPT_msingle_float: 229 if (!TARGET_SINGLE_FPU) 230 warning_at (loc, 0, 231 "%<-msingle-float%> option equivalent to %<-mhard-float%>"); 232 /* -msingle-float implies -mno-double-float and TARGET_HARD_FLOAT. */ 233 opts->x_rs6000_double_float = 0; 234 opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT; 235 opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT; 236 break; 237 238 case OPT_mdouble_float: 239 /* -mdouble-float implies -msingle-float and TARGET_HARD_FLOAT. */ 240 opts->x_rs6000_single_float = 1; 241 opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT; 242 opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT; 243 break; 244 245 case OPT_msimple_fpu: 246 if (!TARGET_SINGLE_FPU) 247 warning_at (loc, 0, "%<-msimple-fpu%> option ignored"); 248 break; 249 250 case OPT_mhard_float: 251 /* -mhard_float implies -msingle-float and -mdouble-float. */ 252 opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1; 253 break; 254 255 case OPT_msoft_float: 256 /* -msoft_float implies -mnosingle-float and -mnodouble-float. */ 257 opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0; 258 break; 259 260 case OPT_mfpu_: 261 fpu_type = (enum fpu_type_t) value; 262 if (fpu_type != FPU_NONE) 263 { 264 /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on 265 HARD_FLOAT. */ 266 opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT; 267 opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT; 268 opts->x_rs6000_xilinx_fpu = 1; 269 if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL) 270 opts->x_rs6000_single_float = 1; 271 if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL) 272 opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1; 273 if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE) 274 opts->x_rs6000_simple_fpu = 1; 275 } 276 else 277 { 278 /* -mfpu=none is equivalent to -msoft-float. */ 279 opts->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT; 280 opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT; 281 opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0; 282 } 283 break; 284 285 case OPT_mrecip: 286 opts->x_rs6000_recip_name = (value) ? "default" : "none"; 287 break; 288 } 289 return true; 290 } 291 292 /* -fsplit-stack uses a field in the TCB, available with glibc-2.19. 293 We also allow 2.18 because alignment padding guarantees that the 294 space is available there too. */ 295 296 static bool 297 rs6000_supports_split_stack (bool report, 298 struct gcc_options *opts ATTRIBUTE_UNUSED) 299 { 300 #ifndef TARGET_GLIBC_MAJOR 301 #define TARGET_GLIBC_MAJOR 0 302 #endif 303 #ifndef TARGET_GLIBC_MINOR 304 #define TARGET_GLIBC_MINOR 0 305 #endif 306 /* Note: Can't test DEFAULT_ABI here, it isn't set until later. */ 307 if (TARGET_GLIBC_MAJOR * 1000 + TARGET_GLIBC_MINOR >= 2018 308 && TARGET_64BIT 309 && TARGET_ELF) 310 return true; 311 312 if (report) 313 error ("%<-fsplit-stack%> currently only supported on PowerPC64 GNU/Linux with glibc-2.18 or later"); 314 return false; 315 } 316 317 #undef TARGET_HANDLE_OPTION 318 #define TARGET_HANDLE_OPTION rs6000_handle_option 319 320 #undef TARGET_OPTION_INIT_STRUCT 321 #define TARGET_OPTION_INIT_STRUCT rs6000_option_init_struct 322 323 #undef TARGET_OPTION_DEFAULT_PARAMS 324 #define TARGET_OPTION_DEFAULT_PARAMS rs6000_option_default_params 325 326 #undef TARGET_OPTION_OPTIMIZATION_TABLE 327 #define TARGET_OPTION_OPTIMIZATION_TABLE rs6000_option_optimization_table 328 329 #undef TARGET_SUPPORTS_SPLIT_STACK 330 #define TARGET_SUPPORTS_SPLIT_STACK rs6000_supports_split_stack 331 332 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; 333