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