1/* Definitions of target machine GNU compiler. 32bit VMS version.
2   Copyright (C) 2009-2015 Free Software Foundation, Inc.
3   Contributed by Douglas B Rupp (rupp@gnat.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 "hash-set.h"
25#include "machmode.h"
26#include "vec.h"
27#include "double-int.h"
28#include "input.h"
29#include "alias.h"
30#include "symtab.h"
31#include "options.h"
32#include "wide-int.h"
33#include "inchash.h"
34#include "tree.h"
35#include "stringpool.h"
36#include "vms-protos.h"
37#include "ggc.h"
38#include "target.h"
39#include "output.h"
40#include "tm.h"
41#include "dwarf2out.h"
42
43/* Correlation of standard CRTL names with DECCRTL function names.  */
44
45/* Name is for a function that allocate memory.  Use the 64bit version
46   if -mmalloc64.  */
47#define VMS_CRTL_MALLOC	(1 << 0)
48
49/* If long pointer are enabled, use _NAME64 instead.  */
50#define VMS_CRTL_64	(1 << 1)
51
52/* Prepend s/f before the name.  To be applied after the previous rule.
53   use 's' for S float, 'f' for IEEE 32.  */
54#define VMS_CRTL_FLOAT32  (1 << 2)
55
56/* Prepend t/g/d before the name.  To be applied after the previous rule.
57   use 'g' for VAX G float, 'd' for VAX D float, 't' for IEEE 64.  */
58#define VMS_CRTL_FLOAT64  (1 << 3)
59
60/* Prepend d before the name, only if using VAX fp.  */
61#define VMS_CRTL_FLOAT64_VAXD  (1 << 4)
62
63/* Prepend x before the name for if 128 bit long doubles are enabled.  This
64   concern mostly 'printf'-like functions.  */
65#define VMS_CRTL_FLOAT128 (1 << 5)
66
67/* From xxx, create xxx, xxxf, xxxl using MATH$XXX_T, MATH$XXX_S
68   and MATH$XXX{_X} if DPML is used.  */
69#define VMS_CRTL_DPML (1 << 6)
70
71/* Together with DPML, it means that all variant (ie xxx, xxxf and xxxl) are
72   overridden by decc.  Without DPML, it means this is a variant (ie xxxf
73   or xxxl) of a function.  */
74#define VMS_CRTL_NODPML (1 << 7)
75
76/* Prepend __bsd44_ before the name.  To be applied after the P64
77   rule.  */
78#define VMS_CRTL_BSD44	(1 << 8)
79
80/* Define only in 32 bits mode, as this has no 64 bit variants.
81   Concerns getopt/getarg.  */
82#define VMS_CRTL_32ONLY (1 << 9)
83
84/* GLobal data prefix (ga_, gl_...)  */
85#define VMS_CRTL_G_MASK (7 << 10)
86#define VMS_CRTL_G_NONE (0 << 10)
87#define VMS_CRTL_GA	(1 << 10)
88#define VMS_CRTL_GL	(2 << 10)
89
90/* Append '_2'.  Not compatible with 64.  */
91#define VMS_CRTL_FLOATV2 (1 << 13)
92
93struct vms_crtl_name
94{
95  /* The standard C name.  */
96  const char *const name;
97
98  /* Flags to drive the translation.  */
99  unsigned int flags;
100};
101
102/* Map for the translation.  */
103
104static const struct vms_crtl_name vms_crtl_names[] =
105  {
106#include "vms-crtlmap.h"
107  };
108
109/* Number of entires in the above array.  */
110
111#define NBR_CRTL_NAMES (sizeof (vms_crtl_names) / sizeof (*vms_crtl_names))
112
113/* List of aliased identifiers.  They must be persistent across gc.  */
114
115static GTY(()) vec<tree, va_gc> *aliases_id;
116
117/* Add a CRTL translation.  This simply use the transparent alias
118   mechanism, which is platform independent and works with the
119   #pragma extern_prefix (which set the assembler name).  */
120
121static void
122vms_add_crtl_xlat (const char *name, size_t nlen,
123                   const char *id_str, size_t id_len)
124{
125  tree targ;
126
127  /* printf ("vms crtl: %.*s -> %.*s\n", nlen, name, id_len, id_str); */
128
129  targ = get_identifier_with_length (name, nlen);
130  gcc_assert (!IDENTIFIER_TRANSPARENT_ALIAS (targ));
131  IDENTIFIER_TRANSPARENT_ALIAS (targ) = 1;
132  TREE_CHAIN (targ) = get_identifier_with_length (id_str, id_len);
133
134  vec_safe_push (aliases_id, targ);
135}
136
137/* Do VMS specific stuff on builtins: disable the ones that are not
138   standard, mangle names.  */
139
140void
141vms_patch_builtins (void)
142{
143  /* enum built_in_function bi; */
144  unsigned int i;
145
146  /* Fwrite on VMS is non-standard.  */
147  if (builtin_decl_implicit_p (BUILT_IN_FWRITE))
148    set_builtin_decl_implicit_p (BUILT_IN_FWRITE, false);
149
150  if (builtin_decl_implicit_p (BUILT_IN_FWRITE_UNLOCKED))
151    set_builtin_decl_implicit_p (BUILT_IN_FWRITE_UNLOCKED, false);
152
153  /* Define aliases for names.  */
154  for (i = 0; i < NBR_CRTL_NAMES; i++)
155    {
156      const struct vms_crtl_name *n = &vms_crtl_names[i];
157      char res[VMS_CRTL_MAXLEN + 3 + 9 + 1 + 1];
158      int rlen;
159      int nlen = strlen (n->name);
160
161      /* Discard 32ONLY if using 64 bit pointers.  */
162      if ((n->flags & VMS_CRTL_32ONLY)
163	  && flag_vms_pointer_size == VMS_POINTER_SIZE_64)
164	continue;
165
166      /* Handle DPML unless overridden by decc.  */
167      if ((n->flags & VMS_CRTL_DPML)
168	  && !(n->flags & VMS_CRTL_NODPML))
169	{
170	  const char *p;
171          char alt[VMS_CRTL_MAXLEN + 3];
172
173	  memcpy (res, "MATH$", 5);
174	  rlen = 5;
175	  for (p = n->name; *p; p++)
176	    res[rlen++] = TOUPPER (*p);
177	  res[rlen++] = '_';
178	  res[rlen++] = 'T';
179
180	  /* Double version.  */
181	  if (!(n->flags & VMS_CRTL_FLOAT64))
182	    vms_add_crtl_xlat (n->name, nlen, res, rlen);
183
184	  /* Float version.  */
185	  res[rlen - 1] = 'S';
186	  memcpy (alt, n->name, nlen);
187	  alt[nlen] = 'f';
188	  vms_add_crtl_xlat (alt, nlen + 1, res, rlen);
189
190	  /* Long double version.  */
191	  res[rlen - 1] = (LONG_DOUBLE_TYPE_SIZE == 128 ? 'X' : 'T');
192	  alt[nlen] = 'l';
193	  vms_add_crtl_xlat (alt, nlen + 1, res, rlen);
194
195	  if (!(n->flags & (VMS_CRTL_FLOAT32 | VMS_CRTL_FLOAT64)))
196	    continue;
197	}
198
199      if (n->flags & VMS_CRTL_FLOAT64_VAXD)
200	continue;
201
202      /* Add the dec-c prefix.  */
203      memcpy (res, "decc$", 5);
204      rlen = 5;
205
206      if (n->flags & VMS_CRTL_BSD44)
207        {
208          memcpy (res + rlen, "__bsd44_", 8);
209          rlen += 8;
210        }
211
212      if ((n->flags & VMS_CRTL_G_MASK) != VMS_CRTL_G_NONE)
213        {
214	  res[rlen++] = 'g';
215	  switch (n->flags & VMS_CRTL_G_MASK)
216	    {
217	    case VMS_CRTL_GA:
218	      res[rlen++] = 'a';
219	      break;
220	    case VMS_CRTL_GL:
221	      res[rlen++] = 'l';
222	      break;
223	    default:
224	      gcc_unreachable ();
225	    }
226	  res[rlen++] = '_';
227        }
228
229      if (n->flags & VMS_CRTL_FLOAT32)
230        res[rlen++] = 'f';
231
232      if (n->flags & VMS_CRTL_FLOAT64)
233        res[rlen++] = 't';
234
235      if ((n->flags & VMS_CRTL_FLOAT128) && LONG_DOUBLE_TYPE_SIZE == 128)
236        res[rlen++] = 'x';
237
238      memcpy (res + rlen, n->name, nlen);
239
240      if ((n->flags & VMS_CRTL_64) == 0)
241	{
242	  rlen += nlen;
243
244	  if (n->flags & VMS_CRTL_FLOATV2)
245	    {
246	      res[rlen++] = '_';
247	      res[rlen++] = '2';
248	    }
249	  vms_add_crtl_xlat (n->name, nlen, res, rlen);
250	}
251      else
252        {
253          char alt[VMS_CRTL_MAXLEN + 3];
254          bool use_64;
255
256          /* Add three translations:
257             _X32 -> X
258             _X64 -> _X64
259             X -> X if short, _X64 if long.  */
260          alt[0] = '_';
261          memcpy (alt + 1, n->name, nlen);
262          alt[1 + nlen + 0] = '3';
263          alt[1 + nlen + 1] = '2';
264          alt[1 + nlen + 2] = 0;
265          vms_add_crtl_xlat (alt, nlen + 3, res, rlen + nlen);
266
267          use_64 = (((n->flags & VMS_CRTL_64)
268                     && flag_vms_pointer_size == VMS_POINTER_SIZE_64)
269                    || ((n->flags & VMS_CRTL_MALLOC)
270                        && flag_vms_malloc64
271                        && flag_vms_pointer_size != VMS_POINTER_SIZE_NONE));
272          if (!use_64)
273            vms_add_crtl_xlat (n->name, nlen, res, rlen + nlen);
274
275          res[rlen++] = '_';
276          memcpy (res + rlen, n->name, nlen);
277          res[rlen + nlen + 0] = '6';
278          res[rlen + nlen + 1] = '4';
279
280          if (use_64)
281            vms_add_crtl_xlat (n->name, nlen, res, rlen + nlen + 2);
282
283          alt[1 + nlen + 0] = '6';
284          alt[1 + nlen + 1] = '4';
285          vms_add_crtl_xlat (alt, nlen + 3, res, rlen + nlen + 2);
286        }
287    }
288}
289
290/* Always default to .text section.  */
291
292section *
293vms_function_section (tree decl ATTRIBUTE_UNUSED,
294                      enum node_frequency freq ATTRIBUTE_UNUSED,
295                      bool startup ATTRIBUTE_UNUSED,
296                      bool exit ATTRIBUTE_UNUSED)
297{
298  return NULL;
299}
300
301/* Additionnal VMS specific code for start_function.  */
302
303/* Must be kept in sync with libgcc/config/vms/vms-ucrt0.c  */
304#define VMS_MAIN_FLAGS_SYMBOL "__gcc_main_flags"
305#define MAIN_FLAG_64BIT (1 << 0)
306#define MAIN_FLAG_POSIX (1 << 1)
307
308void
309vms_start_function (const char *fnname)
310{
311#if VMS_DEBUGGING_INFO
312  if (vms_debug_main
313      && debug_info_level > DINFO_LEVEL_NONE
314      && strncmp (vms_debug_main, fnname, strlen (vms_debug_main)) == 0)
315    {
316      targetm.asm_out.globalize_label (asm_out_file, VMS_DEBUG_MAIN_POINTER);
317      ASM_OUTPUT_DEF (asm_out_file, VMS_DEBUG_MAIN_POINTER, fnname);
318      dwarf2out_vms_debug_main_pointer ();
319      vms_debug_main = 0;
320    }
321#endif
322
323  /* Registers flags used for function main.  This is necessary for
324     crt0 code.  */
325  if (strcmp (fnname, "main") == 0)
326    {
327      unsigned int flags = 0;
328
329      if (flag_vms_pointer_size == VMS_POINTER_SIZE_64)
330	flags |= MAIN_FLAG_64BIT;
331      if (!flag_vms_return_codes)
332	flags |= MAIN_FLAG_POSIX;
333
334      targetm.asm_out.globalize_label (asm_out_file, VMS_MAIN_FLAGS_SYMBOL);
335      assemble_name (asm_out_file, VMS_MAIN_FLAGS_SYMBOL);
336      fprintf (asm_out_file, " = %u\n", flags);
337    }
338}
339
340#include "gt-vms.h"
341