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