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]

Re: [PATCH] VMS ABI stuff for IA64


On Wed, 2009-07-29 at 19:47 -0700, Douglas B Rupp wrote:
 
> -/* ??? 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

I don't think these old '#if 0' blocks are adding any useful
information, let's just remove them (TARGET_PROMOTE_FUNCTION_ARGS,
TARGET_PROMOTE_FUNCTION_RETURN, and TARGET_PROMOTE_PROTOTYPES) and then
move the defines that VMS needs into vms.h where they won't need to be
in ifdef's.


> @@ -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
> +

I think this should be an ifdef using PROMOTE_FUNCTION_MODE and then
TARGET_ABI_OPEN_VMS should be checked in the if statement.  Ideally
there should be a default PROMOTE_FUNCTION_MODE function so that we
wouldn't need an ifdef at all but that isn't something that needs to be
addressed in this patch.

>        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)
>  
>  

This first patch is OK if you move the TARGET_PROMOTE_FUNCTION_ARGS and
TARGET_PROMOTE_FUNCTION_RETURN defines and change the
TARGET_ABI_OPEN_VMS ifdef to PROMOTE_FUNCTION_ARGS.  I'll work on
reviewing the other parts of the patch and hopefully get through them
all before the end of next week.

Steve Ellcey
sje@cup.hp.com


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