This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] VMS ABI stuff for IA64
- From: Steve Ellcey <sje at cup dot hp dot com>
- To: Douglas B Rupp <rupp at gnat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, wilson at codesourcery dot com
- Date: Fri, 31 Jul 2009 10:51:28 -0700
- Subject: Re: [PATCH] VMS ABI stuff for IA64
- References: <4A7109DB.7030909@gnat.com>
- Reply-to: sje at cup dot hp dot com
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