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