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