1 /* VMS specific, C compiler specific functions.
2 Copyright (C) 2011-2019 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
vms_pragma_nostandard(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_standard(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_member_alignment(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_nomember_alignment(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_extern_model(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_message(cpp_reader * pfile ATTRIBUTE_UNUSED)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
vms_pragma_extern_prefix(cpp_reader * ARG_UNUSED (dummy))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
handle_pragma_pointer_size(const char * pragma_name)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
vms_pragma_pointer_size(cpp_reader * ARG_UNUSED (dummy))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
vms_pragma_required_pointer_size(cpp_reader * ARG_UNUSED (dummy))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
vms_c_register_pragma(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 *
vms_construct_include_filename(const char * fname,cpp_dir * dir)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
vms_c_register_includes(const char * sysroot,const char * iprefix ATTRIBUTE_UNUSED,int stdinc)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
vms_c_common_override_options(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
vms_c_get_crtl_ver(void)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
vms_c_get_vms_ver(void)486 vms_c_get_vms_ver (void)
487 {
488 return VMS_DEFAULT_VMS_VER;
489 }
490