PageRenderTime 19ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/gcc/config/vms/vms-c.cc

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