xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/vms/vms-c.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
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 
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 #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 
47 static void
48 vms_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 
58 static void
59 vms_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.  */
68 static int saved_member_alignment;
69 
70 /* Handle '#pragma member_alignment'.  */
71 
72 static void
73 vms_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 
116 static void
117 vms_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 
169 enum 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.  */
195 static enum extern_model_kind current_extern_model;
196 static enum extern_model_kind saved_extern_model;
197 
198 /* Partial handling of '#pragma extern_model'.  */
199 
200 static void
201 vms_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 
251 static void
252 vms_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 
263 static GTY(()) tree saved_extern_prefix;
264 
265 static void
266 vms_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 
299 static machine_mode saved_pointer_mode;
300 
301 static void
302 handle_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 
345 static void
346 vms_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 
355 static void
356 vms_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 
363 void
364 vms_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 
390 static char *
391 vms_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.  */
417 static const char * const vms_std_modules[] = { "rtldef", "starlet_c", NULL };
418 
419 /* Find include modules in the include path.  */
420 
421 void
422 vms_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 
463 void
464 vms_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 
485 int
486 vms_c_get_crtl_ver (void)
487 {
488   return VMS_DEFAULT_CRTL_VER;
489 }
490 
491 /* The default value for _VMS_VER macro.  */
492 
493 int
494 vms_c_get_vms_ver (void)
495 {
496   return VMS_DEFAULT_VMS_VER;
497 }
498