This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] IA64 VMS ABI issues (2nd try)



I had to rework this patch for TARGET_PROMOTE_FUNCTION_MODE and I also combined it with the TARGET_VALID_POINTER_MODE patch. Seemed like it needed re-approval.


OK to commit?

--Douglas Rupp
AdaCore

2009-08-15  Douglas B Rupp  <rupp@gnat.com>
	    Olivier Hainque  <hainque@adacore.com>

	* config/ia64/ia64.c: Include libfuncs.h.
	(TARGET_PROMOTE_FUNCITON_MODE): Define target macro.
	(ia64_expand_call): Use reg 25 on VMS.
	(ia64_initialize_trampoline): Fix for VMS ABI.
	(ia64_function_arg_offset): Always returns 0 when TARGET_ABI_OPEN_VMS.
	(ia64_function_arg): Initialize reg 25 on VMS.
	Fix OpenVMS ABI issues for varargs.
	For OpenVMS, emit the Argument Information register set in the
	incoming/sibcall case as well.
	(ia64_arg_type): New function.
	(ia64_function_arg_advance): Keep track of cum->words.
	Fix OpenVMS ABI issues for varargs.
	(ia64_function_value): On VMS, promote mode of non-aggregate types.
	(ia64_override_options): Set flag_no_common on VMS.
	(ia64_init_builtins): Disable FWRITE builtin.
	(ia64_asm_output_external): Call DO_CRTL_NAMES.
	(ia64_vms_init_libfuncs): Add decc$ routines.
	(ia64_vms_valid_pointer_mode): New function.
	(ia64_struct_value_rtx): Allways NULL_RTX on VMS.
	(ia64_promote_function_mode): New function
	* config/ia64/ia64.h (TARGET_ABI_OPEN_VMS): Define as 0 for default.
	(LONG_DOUBLE_TYPE_SIZE): Force to 64 on VMS.
	(LIBCGC2_LONG_DOUBLE_TYPE_SIZE): Likewise.
	(INIT_CUMULATIVE_ARGS): Add atypes for VMS.
	(INIT_CUMULATIVE_INCOMING_ARGS): Likewise.
	(ASM_OUTPUT_DEF): Use ISDIGIT instead of isdigit.
	Suppress trailing '#' if VALUE is numeric.
	* config/ia64/vms.h (PROMOTE_FUNCTION_MODE): Remove, code moved to
	ia64_promote_function_mode.
	(TARGET_VALID_POINTER_MODE): Define.

diff -rupN gcc-head-src-orig/gcc/config/ia64/ia64.c gcc-head-src/gcc/config/ia64/ia64.c
--- gcc/config/ia64/ia64.c	2009-08-01 15:03:34.000000000 -0700
+++ gcc/config/ia64/ia64.c	2009-08-15 10:48:47.023922607 -0700
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  
 #include "function.h"
 #include "ggc.h"
 #include "basic-block.h"
+#include "libfuncs.h"
 #include "toplev.h"
 #include "sched-int.h"
 #include "timevar.h"
@@ -276,6 +277,8 @@ static void ia64_vms_init_libfuncs (void
      ATTRIBUTE_UNUSED;
 static void ia64_soft_fp_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
+static bool ia64_vms_valid_pointer_mode (enum machine_mode mode)
+     ATTRIBUTE_UNUSED;
 
 static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
 static tree ia64_handle_version_id_attribute (tree *, tree, tree, int, bool *);
@@ -290,6 +291,11 @@ static const char *ia64_invalid_conversi
 static const char *ia64_invalid_unary_op (int, const_tree);
 static const char *ia64_invalid_binary_op (int, const_tree, const_tree);
 static enum machine_mode ia64_c_mode_for_suffix (char);
+static enum machine_mode ia64_promote_function_mode (const_tree,
+						     enum machine_mode,
+						     int *,
+						     const_tree,
+						     int);
 
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ia64_attribute_table[] =
@@ -457,11 +463,8 @@ static const struct attribute_spec ia64_
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL ia64_output_dwarf_dtprel
 #endif
 
-/* ??? ABI doesn't allow us to define this.  */
-#if 0
 #undef TARGET_PROMOTE_FUNCTION_MODE
-#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
-#endif
+#define TARGET_PROMOTE_FUNCTION_MODE ia64_promote_function_mode
 
 /* ??? Investigate.  */
 #if 0
@@ -1918,6 +1921,10 @@ ia64_expand_call (rtx retval, rtx addr, 
 
   if (sibcall_p)
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
+
+  if (TARGET_ABI_OPEN_VMS)
+    use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+	     gen_rtx_REG (DImode, GR_REG (25)));
 }
 
 static void
@@ -3832,7 +3839,7 @@ ia64_dbx_register_number (int regno)
 void
 ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
 {
-  rtx addr_reg, eight = GEN_INT (8);
+  rtx addr_reg, tramp, eight = GEN_INT (8);
 
   /* The Intel assembler requires that the global __ia64_trampoline symbol
      be declared explicitly */
@@ -3859,8 +3866,21 @@ ia64_initialize_trampoline (rtx addr, rt
 
   /* The first two words are the fake descriptor:
      __ia64_trampoline, ADDR+16.  */
-  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
-		  gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline"));
+  tramp = gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline");
+  if (TARGET_ABI_OPEN_VMS)
+    {
+      /* HP decided to break the ELF ABI on VMS (to deal with an ambiguity
+	 in the Macro-32 compiler) and changed the semantics of the LTOFF22
+	 relocation against function symbols to make it identical to the
+	 LTOFF_FPTR22 relocation.  Emit the latter directly to stay within
+	 strict ELF and dereference to get the bare code address.  */
+      rtx reg = gen_reg_rtx (Pmode);
+      SYMBOL_REF_FLAGS (tramp) |= SYMBOL_FLAG_FUNCTION;
+      emit_move_insn (reg, tramp);
+      emit_move_insn (reg, gen_rtx_MEM (Pmode, reg));
+      tramp = reg;
+   }
+  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), tramp);
   emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
 
   emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
@@ -4017,7 +4037,8 @@ ia64_function_arg_words (tree type, enum
 static int
 ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
 {
-  if ((cum->words & 1) == 0)
+  /* No registers are skipped on VMS.  */
+  if (TARGET_ABI_OPEN_VMS || (cum->words & 1) == 0)
     return 0;
 
   if (type
@@ -4042,6 +4063,24 @@ ia64_function_arg (CUMULATIVE_ARGS *cum,
   int offset = ia64_function_arg_offset (cum, type, words);
   enum machine_mode hfa_mode = VOIDmode;
 
+  /* For OPEN VMS, emit the instruction setting up the argument register here,
+     when we know this will be together with the other arguments setup related
+     insns.  This is not the conceptually best place to do this, but this is
+     the easiest as we have convenient access to cumulative args info.  */
+
+  if (TARGET_ABI_OPEN_VMS && mode == VOIDmode && type == void_type_node
+      && named == 1)
+    {
+      unsigned HOST_WIDE_INT regval = cum->words;
+      int i;
+
+      for (i = 0; i < 8; i++)
+	regval |= ((int) cum->atypes[i]) << (i * 3 + 8);
+
+      emit_move_insn (gen_rtx_REG (DImode, GR_REG (25)),
+		      GEN_INT (regval));
+    }
+
   /* If all argument slots are used, then it must go on the stack.  */
   if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
     return 0;
@@ -4131,6 +4170,15 @@ ia64_function_arg (CUMULATIVE_ARGS *cum,
 	}
       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
+  
+  /* On OpenVMS variable argument is either in Rn or Fn.  */
+  else if (TARGET_ABI_OPEN_VMS && named == 0)
+    {
+      if (FLOAT_MODE_P (mode))
+	return gen_rtx_REG (mode, FR_ARG_FIRST + cum->words);
+      else
+	return gen_rtx_REG (mode, basereg + cum->words);
+    }
 
   /* Integral and aggregates go in general registers.  If we have run out of
      FR registers, then FP values must also go in general registers.  This can
@@ -4223,6 +4271,22 @@ ia64_arg_partial_bytes (CUMULATIVE_ARGS 
   return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
 }
 
+/* Return ivms_arg_type based on machine_mode.  */
+
+static enum ivms_arg_type
+ia64_arg_type (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case SFmode:
+      return FS;
+    case DFmode:
+      return FT;
+    default:
+      return I64;
+    }
+}
+
 /* Update CUM to point after this argument.  This is patterned after
    ia64_function_arg.  */
 
@@ -4236,8 +4300,12 @@ ia64_function_arg_advance (CUMULATIVE_AR
 
   /* If all arg slots are already full, then there is nothing to do.  */
   if (cum->words >= MAX_ARGUMENT_SLOTS)
-    return;
+    {
+      cum->words += words + offset;
+      return;
+    }
 
+  cum->atypes[cum->words] = ia64_arg_type (mode);
   cum->words += words + offset;
 
   /* Check for and handle homogeneous FP aggregates.  */
@@ -4280,6 +4348,13 @@ ia64_function_arg_advance (CUMULATIVE_AR
       cum->fp_regs = fp_regs;
     }
 
+  /* On OpenVMS variable argument is either in Rn or Fn.  */
+  else if (TARGET_ABI_OPEN_VMS && named == 0)
+    {
+      cum->int_regs = cum->words;
+      cum->fp_regs = cum->words;
+    }
+
   /* Integral and aggregates go in general registers.  So do TFmode FP values.
      If we have run out of FR registers, then other FP values must also go in
      general registers.  This can happen when we have a SFmode HFA.  */
@@ -4424,10 +4499,11 @@ ia64_return_in_memory (const_tree valtyp
 /* Return rtx for register that holds the function return value.  */
 
 rtx
-ia64_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
+ia64_function_value (const_tree valtype, const_tree func)
 {
   enum machine_mode mode;
   enum machine_mode hfa_mode;
+  int unsignedp;
 
   mode = TYPE_MODE (valtype);
   hfa_mode = hfa_element_mode (valtype, 0);
@@ -4498,6 +4574,10 @@ ia64_function_value (const_tree valtype,
 	  return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
 	}
 
+      mode = ia64_promote_function_mode (valtype, mode, &unsignedp,
+					 func ? TREE_TYPE (func) : NULL_TREE,
+					 true);
+
       return gen_rtx_REG (mode, GR_RET_FIRST);
     }
 }
@@ -5306,6 +5386,9 @@ ia64_override_options (void)
     align_functions = 64;
   if (align_loops <= 0)
     align_loops = 32;
+
+  if (TARGET_ABI_OPEN_VMS)
+    flag_no_common = 1;
 }
 
 /* Initialize the record of emitted frame related registers.  */
@@ -9830,6 +9913,13 @@ ia64_init_builtins (void)
     (*lang_hooks.types.register_builtin_type) (long_double_type_node,
 					       "__float128");
 
+  /* Fwrite on VMS is non-standard.  */
+  if (TARGET_ABI_OPEN_VMS)
+    {
+      implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
+      implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
+    }
+
 #define def_builtin(name, type, code)					\
   add_builtin_function ((name), (type), (code), BUILT_IN_MD,	\
 		       NULL, NULL_TREE)
@@ -9942,6 +10032,10 @@ ia64_asm_output_external (FILE *file, tr
       int need_visibility = ((*targetm.binds_local_p) (decl)
 			     && maybe_assemble_visibility (decl));
 
+#ifdef DO_CRTL_NAMES
+      DO_CRTL_NAMES;
+#endif
+
       /* GNU as does not need anything here, but the HP linker does
 	 need something for external functions.  */
       if ((TARGET_HPUX_LD || !TARGET_GNU_AS)
@@ -10044,6 +10138,11 @@ ia64_vms_init_libfuncs (void)
   set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
   set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
   set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
+  abort_libfunc = init_one_libfunc ("decc$abort");
+  memcmp_libfunc = init_one_libfunc ("decc$memcmp");
+#ifdef MEM_LIBFUNCS_INIT
+  MEM_LIBFUNCS_INIT;
+#endif
 }
 
 /* Rename the TFmode libfuncs available from soft-fp in glibc using
@@ -10074,6 +10175,12 @@ static void
 ia64_soft_fp_init_libfuncs (void)
 {
 }
+
+static bool
+ia64_vms_valid_pointer_mode (enum machine_mode mode)
+{
+  return (mode == SImode || mode == DImode);
+}
 
 /* For HPUX, it is illegal to have relocations in shared segments.  */
 
@@ -10300,7 +10399,8 @@ static rtx
 ia64_struct_value_rtx (tree fntype,
 		       int incoming ATTRIBUTE_UNUSED)
 {
-  if (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype))
+  if (TARGET_ABI_OPEN_VMS ||
+      (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype)))
     return NULL_RTX;
   return gen_rtx_REG (Pmode, GR_REG (8));
 }
@@ -10565,6 +10665,42 @@ ia64_c_mode_for_suffix (char suffix)
   return VOIDmode;
 }
 
+static enum machine_mode
+ia64_promote_function_mode (const_tree type,
+			    enum machine_mode mode,
+			    int *punsignedp,
+			    const_tree funtype ATTRIBUTE_UNUSED,
+			    int for_return ATTRIBUTE_UNUSED)
+{
+  /* Special processing required for OpenVMS ...  */
+
+  if (!TARGET_ABI_OPEN_VMS)
+    return mode;
+
+  /* HP OpenVMS Calling Standard dated June, 2004, that describes
+     HP OpenVMS I64 Version 8.2EFT,
+     chapter 4 "OpenVMS I64 Conventions"
+     section 4.7 "Procedure Linkage"
+     subsection 4.7.5.2, "Normal Register Parameters"
+
+     "Unsigned integral (except unsigned 32-bit), set, and VAX floating-point
+     values passed in registers are zero-filled; signed integral values as
+     well as unsigned 32-bit integral values are sign-extended to 64 bits.
+     For all other types passed in the general registers, unused bits are
+     undefined."  */
+
+  if (!AGGREGATE_TYPE_P (type)
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    {
+      if (mode == SImode)
+	*punsignedp = 0;
+      return DImode;
+    }
+  else
+    return promote_mode (type, mode, punsignedp);
+}
+   
 static GTY(()) rtx ia64_dconst_0_5_rtx;
 
 rtx
diff -rupN gcc-head-src-orig/gcc/config/ia64/ia64.h gcc-head-src/gcc/config/ia64/ia64.h
--- gcc/config/ia64/ia64.h	2009-05-21 16:51:22.000000000 -0700
+++ gcc/config/ia64/ia64.h	2009-08-15 09:51:24.667412430 -0700
@@ -73,6 +73,8 @@ extern unsigned int ia64_section_thresho
 #define TARGET_HPUX		0
 #define TARGET_HPUX_LD		0
 
+#define TARGET_ABI_OPEN_VMS 0
+
 #ifndef TARGET_ILP32
 #define TARGET_ILP32 0
 #endif
@@ -279,11 +281,17 @@ while (0)
 
 #define DOUBLE_TYPE_SIZE 64
 
-/* long double is XFmode normally, TFmode for HPUX.  */
-#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 80)
+/* long double is XFmode normally, and TFmode for HPUX.  It should be
+   TFmode for VMS as well but we only support up to DFmode now.  */
+#define LONG_DOUBLE_TYPE_SIZE \
+  (TARGET_HPUX ? 128 \
+   : TARGET_ABI_OPEN_VMS ? 64 \
+   : 80)
+
+/* We always want the XFmode operations from libgcc2.c, except on VMS
+   where this yields references to unimplemented "insns".  */
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE  (TARGET_ABI_OPEN_VMS ? 64 : 80)
 
-/* We always want the XFmode operations from libgcc2.c.  */
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
 
 /* On HP-UX, we use the l suffix for TFmode in libgcc2.c.  */
 #define LIBGCC2_TF_CEXT l
@@ -1077,12 +1085,16 @@ enum reg_class
    `FUNCTION_ARG' and other related values.  For some target machines, the type
    `int' suffices and can hold the number of bytes of argument so far.  */
 
+enum ivms_arg_type {I64, FF, FD, FG, FS, FT};
+/* VMS floating point formats VAX F, VAX D, VAX G, IEEE S, IEEE T.  */
+
 typedef struct ia64_args
 {
   int words;			/* # words of arguments so far  */
   int int_regs;			/* # GR registers used so far  */
   int fp_regs;			/* # FR registers used so far  */
   int prototype;		/* whether function prototyped  */
+  enum ivms_arg_type atypes[8]; /* which VMS float type or if not float */
 } CUMULATIVE_ARGS;
 
 /* A C statement (sans semicolon) for initializing the variable CUM for the
@@ -1094,6 +1106,9 @@ do {									\
   (CUM).int_regs = 0;							\
   (CUM).fp_regs = 0;							\
   (CUM).prototype = ((FNTYPE) && TYPE_ARG_TYPES (FNTYPE)) || (LIBNAME);	\
+  (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64;	        \
+  (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64;            \
+  (CUM).atypes[6] = (CUM).atypes[7] = I64;                              \
 } while (0)
 
 /* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the
@@ -1108,6 +1123,9 @@ do {									\
   (CUM).int_regs = 0;							\
   (CUM).fp_regs = 0;							\
   (CUM).prototype = 1;							\
+  (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64;	        \
+  (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64;            \
+  (CUM).atypes[6] = (CUM).atypes[7] = I64;                              \
 } while (0)
 
 /* A C statement (sans semicolon) to update the summarizer variable CUM to
@@ -1496,8 +1514,11 @@ do {									\
 do {									\
   assemble_name (STREAM, NAME);						\
   fputs (" = ", STREAM);						\
+  if (ISDIGIT (*VALUE))							\
+    ia64_asm_output_label = 1;						\
   assemble_name (STREAM, VALUE);					\
   fputc ('\n', STREAM);							\
+  ia64_asm_output_label = 0;						\
 } while (0)
 
 
diff -rupN gcc-head-src-orig/gcc/config/ia64/vms.h gcc-head-src/gcc/config/ia64/vms.h
--- gcc/config/ia64/vms.h	2009-08-14 13:38:36.000000000 -0700
+++ gcc/config/ia64/vms.h	2009-08-15 09:54:11.211071837 -0700
@@ -66,26 +66,6 @@ along with GCC; see the file COPYING3.  
 #undef WIDEST_HARDWARE_FP_SIZE
 #define WIDEST_HARDWARE_FP_SIZE 64
 
-/* HP OpenVMS Calling Standard dated June, 2004, that describes
-   HP OpenVMS I64 Version 8.2EFT
-   chapter 4 "OpenVMS I64 Conventions"
-   section 4.7 "Procedure Linkage"
-   subsection 4.7.5.2, "Normal Register Parameters"
-
-   "Unsigned integral (except unsigned 32-bit), set, and VAX
-   floating-point values passed in registers are zero-filled;
-   signed integral values as well as unsigned 32-bit integral
-   values are sign-extended to 64 bits.  For all other types
-   passed in the general registers, unused bits are undefined."  */
-#define PROMOTE_FUNCTION_MODE(MODE,UNSIGNEDP,TYPE)	\
-  if (GET_MODE_CLASS (MODE) == MODE_INT			\
-      && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)		\
-    {							\
-      if ((MODE) == SImode)				\
-	(UNSIGNEDP) = 0;				\
-      (MODE) = DImode;					\
-    }
-
 /* The structure return address arrives as an "argument" on VMS.  */
 #undef PCC_STATIC_STRUCT_RETURN
 
@@ -227,5 +207,8 @@ typedef struct crtl_name_spec
 #define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
   ia64_vms_output_aligned_decl_common (FILE, DECL, NAME, SIZE, ALIGN)
 
+#undef TARGET_VALID_POINTER_MODE
+#define TARGET_VALID_POINTER_MODE ia64_vms_valid_pointer_mode
+
 #undef TARGET_ASM_NAMED_SECTION
 #define TARGET_ASM_NAMED_SECTION ia64_vms_elf_asm_named_section

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]