1 /* VMS specific, C compiler specific functions. 2 Copyright (C) 2011-2020 Free Software Foundation, Inc. 3 Contributed by Tristan Gingold (gingold@adacore.com). 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #define IN_TARGET_CODE 1 22 23 #include "config.h" 24 #include "system.h" 25 #include "coretypes.h" 26 #include "tm.h" 27 #include "tree.h" 28 #include "c-family/c-common.h" 29 #include "c/c-tree.h" 30 #include "memmodel.h" 31 #include "tm_p.h" 32 #include "c-family/c-pragma.h" 33 #include "toplev.h" 34 #include "incpath.h" 35 36 /* '#pragma __nostandard' is simply ignored. */ 37 38 static void 39 vms_pragma_nostandard (cpp_reader *pfile ATTRIBUTE_UNUSED) 40 { 41 tree x; 42 43 if (pragma_lex (&x) != CPP_EOF) 44 warning (OPT_Wpragmas, "junk at end of #pragma __nostandard"); 45 } 46 47 /* '#pragma __standard' is simply ignored. */ 48 49 static void 50 vms_pragma_standard (cpp_reader *pfile ATTRIBUTE_UNUSED) 51 { 52 tree x; 53 54 if (pragma_lex (&x) != CPP_EOF) 55 warning (OPT_Wpragmas, "junk at end of #pragma __standard"); 56 } 57 58 /* Saved member alignment. */ 59 static int saved_member_alignment; 60 61 /* Handle '#pragma member_alignment'. */ 62 63 static void 64 vms_pragma_member_alignment (cpp_reader *pfile ATTRIBUTE_UNUSED) 65 { 66 tree x; 67 int tok; 68 const char *arg; 69 70 tok = pragma_lex (&x); 71 72 if (tok == CPP_EOF) 73 { 74 /* Disable packing. */ 75 maximum_field_alignment = initial_max_fld_align; 76 return; 77 } 78 if (tok != CPP_NAME) 79 { 80 warning (OPT_Wpragmas, 81 "malformed %<#pragma member_alignment%>, ignoring"); 82 return; 83 } 84 85 arg = IDENTIFIER_POINTER (x); 86 /* Accept '__' prefix. */ 87 if (arg[0] == '_' && arg[1] == '_') 88 arg += 2; 89 90 if (strcmp (arg, "save") == 0) 91 saved_member_alignment = maximum_field_alignment; 92 else if (strcmp (arg, "restore") == 0) 93 maximum_field_alignment = saved_member_alignment; 94 else 95 { 96 error ("unknown %<#pragma member_alignment%> name %s", arg); 97 return; 98 } 99 if (pragma_lex (&x) != CPP_EOF) 100 { 101 error ("malformed %<#pragma member_alignment%>"); 102 return; 103 } 104 } 105 106 /* Handle '#pragma nomember_alignment'. */ 107 108 static void 109 vms_pragma_nomember_alignment (cpp_reader *pfile ATTRIBUTE_UNUSED) 110 { 111 tree x; 112 int tok; 113 114 tok = pragma_lex (&x); 115 if (tok == CPP_NAME) 116 { 117 const char *arg = IDENTIFIER_POINTER (x); 118 119 /* Accept '__' prefix. */ 120 if (arg[0] == '_' && arg[1] == '_') 121 arg += 2; 122 123 if (strcmp (arg, "byte") == 0) 124 maximum_field_alignment = 1 * BITS_PER_UNIT; 125 else if (strcmp (arg, "word") == 0) 126 maximum_field_alignment = 2 * BITS_PER_UNIT; 127 else if (strcmp (arg, "longword") == 0) 128 maximum_field_alignment = 4 * BITS_PER_UNIT; 129 else if (strcmp (arg, "quadword") == 0) 130 maximum_field_alignment = 8 * BITS_PER_UNIT; 131 else if (strcmp (arg, "octaword") == 0) 132 maximum_field_alignment = 16 * BITS_PER_UNIT; 133 else 134 { 135 error ("unhandled alignment for %<#pragma nomember_alignment%>"); 136 } 137 138 tok = pragma_lex (&x); 139 } 140 else 141 { 142 /* Enable packing. */ 143 maximum_field_alignment = BITS_PER_UNIT; 144 } 145 146 if (tok != CPP_EOF) 147 { 148 error ("garbage at end of %<#pragma nomember_alignment%>"); 149 return; 150 } 151 } 152 153 /* The 'extern model' for public data. This drives how the following 154 declarations are handled: 155 1) extern int name; 156 2) int name; 157 3) int name = 5; 158 See below for the behavior as implemented by the native compiler. 159 */ 160 161 enum extern_model_kind 162 { 163 /* Create one overlaid section per variable. All the above declarations (1, 164 2 and 3) are handled the same way: they create an overlaid section named 165 NAME (and initialized only for 3). No global symbol is created. 166 This is the VAX C behavior. */ 167 extern_model_common_block, 168 169 /* Like unix: multiple not-initialized declarations are allowed. 170 Only one initialized definition (case 3) is allows, but multiple 171 uninitialize definition (case 2) are allowed. 172 For case 2, this creates both a section named NAME and a global symbol. 173 For case 3, this creates a conditional global symbol defenition and a 174 conditional section definition. 175 This is the traditional UNIX C behavior. */ 176 extern_model_relaxed_refdef, 177 178 /* Like -fno-common. Only one definition (cases 2 and 3) are allowed. 179 This is the ANSI-C model. */ 180 extern_model_strict_refdef, 181 182 /* Declarations creates symbols without storage. */ 183 extern_model_globalvalue 184 }; 185 186 /* Current and saved extern model. */ 187 static enum extern_model_kind current_extern_model; 188 static enum extern_model_kind saved_extern_model; 189 190 /* Partial handling of '#pragma extern_model'. */ 191 192 static void 193 vms_pragma_extern_model (cpp_reader *pfile ATTRIBUTE_UNUSED) 194 { 195 tree x; 196 int tok; 197 const char *arg; 198 199 tok = pragma_lex (&x); 200 201 if (tok != CPP_NAME) 202 { 203 warning (OPT_Wpragmas, "malformed %<#pragma extern_model%>, ignoring"); 204 return; 205 } 206 207 arg = IDENTIFIER_POINTER (x); 208 /* Accept "__" prefix. */ 209 if (arg[0] == '_' && arg[1] == '_') 210 arg += 2; 211 212 if (strcmp (arg, "save") == 0) 213 saved_extern_model = current_extern_model; 214 else if (strcmp (arg, "restore") == 0) 215 current_extern_model = saved_extern_model; 216 else if (strcmp (arg, "relaxed_refdef") == 0) 217 current_extern_model = extern_model_relaxed_refdef; 218 else if (strcmp (arg, "strict_refdef") == 0) 219 current_extern_model = extern_model_strict_refdef; 220 else if (strcmp (arg, "common_block") == 0) 221 current_extern_model = extern_model_common_block; 222 else if (strcmp (arg, "globalvalue") == 0) 223 { 224 sorry ("extern model globalvalue"); 225 return; 226 } 227 else 228 { 229 error ("unknown %<#pragma extern_model%> model %qs", arg); 230 return; 231 } 232 #if 0 233 if (pragma_lex (&x) != CPP_EOF) 234 { 235 permerror (input_location, "junk at end of '#pragma extern_model'"); 236 return; 237 } 238 #endif 239 } 240 241 /* Ignore '#pragma message'. */ 242 243 static void 244 vms_pragma_message (cpp_reader *pfile ATTRIBUTE_UNUSED) 245 { 246 /* Completly ignored. */ 247 #if 0 248 pedwarn (input_location, OPT_Wpragmas, 249 "vms '#pragma __message' is ignored"); 250 #endif 251 } 252 253 /* Handle '#pragma __extern_prefix' */ 254 255 static GTY(()) tree saved_extern_prefix; 256 257 static void 258 vms_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy)) 259 { 260 enum cpp_ttype tok; 261 tree x; 262 263 tok = pragma_lex (&x); 264 if (tok == CPP_NAME) 265 { 266 const char *op = IDENTIFIER_POINTER (x); 267 268 if (!strcmp (op, "__save")) 269 saved_extern_prefix = pragma_extern_prefix; 270 else if (!strcmp (op, "__restore")) 271 pragma_extern_prefix = saved_extern_prefix; 272 else 273 warning (OPT_Wpragmas, 274 "malformed '#pragma __extern_prefix', ignoring"); 275 return; 276 } 277 else if (tok != CPP_STRING) 278 { 279 warning (OPT_Wpragmas, 280 "malformed '#pragma __extern_prefix', ignoring"); 281 } 282 else 283 { 284 /* Note that the length includes the null terminator. */ 285 pragma_extern_prefix = (TREE_STRING_LENGTH (x) > 1 ? x : NULL); 286 } 287 } 288 289 /* #pragma __pointer_size */ 290 291 static machine_mode saved_pointer_mode; 292 293 static void 294 handle_pragma_pointer_size (const char *pragma_name) 295 { 296 enum cpp_ttype tok; 297 tree x; 298 299 tok = pragma_lex (&x); 300 if (tok == CPP_NAME) 301 { 302 const char *op = IDENTIFIER_POINTER (x); 303 304 if (!strcmp (op, "__save")) 305 saved_pointer_mode = c_default_pointer_mode; 306 else if (!strcmp (op, "__restore")) 307 c_default_pointer_mode = saved_pointer_mode; 308 else if (!strcmp (op, "__short")) 309 c_default_pointer_mode = SImode; 310 else if (!strcmp (op, "__long")) 311 c_default_pointer_mode = DImode; 312 else 313 error ("malformed %<#pragma %s%>, ignoring", pragma_name); 314 } 315 else if (tok == CPP_NUMBER) 316 { 317 int val; 318 319 if (TREE_CODE (x) == INTEGER_CST) 320 val = TREE_INT_CST_LOW (x); 321 else 322 val = -1; 323 324 if (val == 32) 325 c_default_pointer_mode = SImode; 326 else if (val == 64) 327 c_default_pointer_mode = DImode; 328 else 329 error ("invalid constant in %<#pragma %s%>", pragma_name); 330 } 331 else 332 { 333 error ("malformed %<#pragma %s%>, ignoring", pragma_name); 334 } 335 } 336 337 static void 338 vms_pragma_pointer_size (cpp_reader * ARG_UNUSED (dummy)) 339 { 340 /* Ignore if no -mpointer-size option. */ 341 if (flag_vms_pointer_size == VMS_POINTER_SIZE_NONE) 342 return; 343 344 handle_pragma_pointer_size ("pointer_size"); 345 } 346 347 static void 348 vms_pragma_required_pointer_size (cpp_reader * ARG_UNUSED (dummy)) 349 { 350 handle_pragma_pointer_size ("required_pointer_size"); 351 } 352 353 /* Add vms-specific pragma. */ 354 355 void 356 vms_c_register_pragma (void) 357 { 358 c_register_pragma (NULL, "__nostandard", vms_pragma_nostandard); 359 c_register_pragma (NULL, "nostandard", vms_pragma_nostandard); 360 c_register_pragma (NULL, "__standard", vms_pragma_standard); 361 c_register_pragma (NULL, "standard", vms_pragma_standard); 362 c_register_pragma (NULL, "__member_alignment", vms_pragma_member_alignment); 363 c_register_pragma (NULL, "member_alignment", vms_pragma_member_alignment); 364 c_register_pragma_with_expansion (NULL, "__nomember_alignment", 365 vms_pragma_nomember_alignment); 366 c_register_pragma_with_expansion (NULL, "nomember_alignment", 367 vms_pragma_nomember_alignment); 368 c_register_pragma (NULL, "__pointer_size", 369 vms_pragma_pointer_size); 370 c_register_pragma (NULL, "__required_pointer_size", 371 vms_pragma_required_pointer_size); 372 c_register_pragma (NULL, "__extern_model", vms_pragma_extern_model); 373 c_register_pragma (NULL, "extern_model", vms_pragma_extern_model); 374 c_register_pragma (NULL, "__message", vms_pragma_message); 375 c_register_pragma (NULL, "__extern_prefix", vms_pragma_extern_prefix); 376 } 377 378 /* Canonicalize the filename (remove directory prefix, force the .h extension), 379 and append it to the directory to create the path, but don't 380 turn / into // or // into ///; // may be a namespace escape. */ 381 382 static char * 383 vms_construct_include_filename (const char *fname, cpp_dir *dir) 384 { 385 size_t dlen, flen; 386 char *path; 387 const char *fbasename = lbasename (fname); 388 size_t i; 389 390 dlen = dir->len; 391 flen = strlen (fbasename) + 2; 392 path = XNEWVEC (char, dlen + 1 + flen + 1); 393 memcpy (path, dir->name, dlen); 394 if (dlen && !IS_DIR_SEPARATOR (path[dlen - 1])) 395 path[dlen++] = '/'; 396 for (i = 0; i < flen; i++) 397 if (fbasename[i] == '.') 398 break; 399 else 400 path[dlen + i] = TOLOWER (fbasename[i]); 401 path[dlen + i + 0] = '.'; 402 path[dlen + i + 1] = 'h'; 403 path[dlen + i + 2] = 0; 404 405 return path; 406 } 407 408 /* Standard modules list. */ 409 static const char * const vms_std_modules[] = { "rtldef", "starlet_c", NULL }; 410 411 /* Find include modules in the include path. */ 412 413 void 414 vms_c_register_includes (const char *sysroot, 415 const char *iprefix ATTRIBUTE_UNUSED, int stdinc) 416 { 417 static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 418 struct cpp_dir *dir; 419 420 /* Add on standard include pathes. */ 421 if (!stdinc) 422 return; 423 424 for (dir = get_added_cpp_dirs (INC_SYSTEM); dir != NULL; dir = dir->next) 425 { 426 const char * const *lib; 427 for (lib = vms_std_modules; *lib != NULL; lib++) 428 { 429 char *path; 430 struct stat st; 431 432 if (sysroot != NULL) 433 path = concat (sysroot, dir->name, dir_separator_str, *lib, NULL); 434 else 435 path = concat (dir->name, dir_separator_str, *lib, NULL); 436 437 if (stat (path, &st) == 0 && S_ISDIR (st.st_mode)) 438 { 439 cpp_dir *p; 440 441 p = XNEW (cpp_dir); 442 p->next = NULL; 443 p->name = path; 444 p->sysp = 1; 445 p->construct = vms_construct_include_filename; 446 p->user_supplied_p = 0; 447 add_cpp_dir_path (p, INC_SYSTEM); 448 } 449 else 450 free (path); 451 } 452 } 453 } 454 455 void 456 vms_c_common_override_options (void) 457 { 458 /* Allow variadic functions without parameters (as declared in starlet). */ 459 flag_allow_parameterless_variadic_functions = TRUE; 460 461 /* Initialize c_default_pointer_mode. */ 462 switch (flag_vms_pointer_size) 463 { 464 case VMS_POINTER_SIZE_NONE: 465 break; 466 case VMS_POINTER_SIZE_32: 467 c_default_pointer_mode = SImode; 468 break; 469 case VMS_POINTER_SIZE_64: 470 c_default_pointer_mode = DImode; 471 break; 472 } 473 } 474 475 /* The default value for _CRTL_VER macro. */ 476 477 int 478 vms_c_get_crtl_ver (void) 479 { 480 return VMS_DEFAULT_CRTL_VER; 481 } 482 483 /* The default value for _VMS_VER macro. */ 484 485 int 486 vms_c_get_vms_ver (void) 487 { 488 return VMS_DEFAULT_VMS_VER; 489 } 490