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] VMS ABI stuff for IA64


This is the first of seven patches to config/ia64. I tried to split them up into easily reviewable components. This first one is basic VMS ABI changes to ia64.[ch].

Authors listed in alphabetical order in ChangeLog.

I tested them en masse with a full bootstrap and make check on ia64-linux and individually with a cross to ia64-linux

OK to commit?

--Douglas B Rupp
AdaCore
2009-07-29  Eric Botcazou  <botcazou@adacore.com>
	    Tristan Gingold  <gingold@adacore.com>
	    Oliver Hainque  <hainque@adacore.com>
	    Douglas B Rupp  <rupp@gnat.com>

	* config/ia64/ia64.c: Include libfuncs.h.
	(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Allow
	on VMS.
	(ia64_initialize_trampoline): Fix for VMS ABI.
	(ia64_expand_call): Use reg 25 on VMS.
	(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_struct_value_rtx): Allways NULL_RTX on VMS.
	* 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.
	(ASM_OUTPUT_DEF): Suppress trailing '#' if VALUE is numeric.

diff -rupN gcc/config/ia64/ia64.c gcc/config/ia64/ia64.c
--- gcc/config/ia64/ia64.c	2008-11-20 23:28:27.000000000 -0800
+++ gcc/config/ia64/ia64.c	2009-01-23 00:23:45.000000000 -0800
@@ -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"
@@ -460,14 +469,14 @@ 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
+/* ??? Non VMS ABI doesn't allow us to define this.  */
+#if TARGET_ABI_OPEN_VMS
 #undef TARGET_PROMOTE_FUNCTION_ARGS
 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
 #endif
 
-/* ??? ABI doesn't allow us to define this.  */
-#if 0
+/* ??? Non VMS ABI doesn't allow us to define this.  */
+#if TARGET_ABI_OPEN_VMS
 #undef TARGET_PROMOTE_FUNCTION_RETURN
 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
 #endif
@@ -1923,6 +2023,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
@@ -3852,7 +3852,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 */
@@ -3879,8 +3879,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),
@@ -4035,7 +4219,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
@@ -4060,6 +4245,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;
@@ -4149,6 +4352,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
@@ -4241,6 +4453,20 @@ ia64_arg_partial_bytes (CUMULATIVE_ARGS 
   return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
 }
 
+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.  */
 
@@ -4254,8 +4480,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.  */
@@ -4298,6 +4528,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.  */
@@ -4445,6 +4682,7 @@ ia64_function_value (const_tree valtype,
 {
   enum machine_mode mode;
   enum machine_mode hfa_mode;
+  int unsignedp ATTRIBUTE_UNUSED = 0;
 
   mode = TYPE_MODE (valtype);
   hfa_mode = hfa_element_mode (valtype, 0);
@@ -4515,6 +4753,11 @@ ia64_function_value (const_tree valtype,
 	  return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
 	}

+#if TARGET_ABI_OPEN_VMS 
+      if (! AGGREGATE_TYPE_P (valtype))
+	PROMOTE_FUNCTION_MODE (mode, unsignedp, valtype);
+#endif
+
       return gen_rtx_REG (mode, GR_RET_FIRST);
     }
 }
@@ -5298,6 +5541,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.  */
@@ -9785,6 +10031,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)
@@ -9875,6 +10127,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)
@@ -9977,6 +10233,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
@@ -10226,7 +10499,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));
 }
diff -rupN gcc/config/ia64/ia64.h gcc/config/ia64/ia64.h
--- gcc/config/ia64/ia64.h	2008-08-30 07:19:01.000000000 -0700
+++ gcc/config/ia64/ia64.h	2009-01-21 15:51:36.000000000 -0800
@@ -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
@@ -1082,12 +1090,15 @@ 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};
+
 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];
 } CUMULATIVE_ARGS;
 
 /* A C statement (sans semicolon) for initializing the variable CUM for the
@@ -1099,6 +1110,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
@@ -1113,6 +1127,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
@@ -1508,8 +1525,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)
 
 

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