From f2972bf8bfded6c265ad6e7e55472070d8538456 Mon Sep 17 00:00:00 2001 From: Douglas B Rupp Date: Sat, 22 Aug 2009 02:50:30 +0000 Subject: [PATCH] ia64.c: Include libfuncs.h. * 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. Co-Authored-By: Olivier Hainque From-SVN: r151009 --- gcc/ChangeLog | 34 ++++++++++ gcc/config/ia64/ia64.c | 166 +++++++++++++++++++++++++++++++++++++++++++++---- gcc/config/ia64/ia64.h | 29 +++++++-- gcc/config/ia64/vms.h | 23 +------ 4 files changed, 217 insertions(+), 35 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 299c6db..d94b046 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2009-08-21 Douglas B Rupp + Olivier Hainque + + * 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. + 2009-08-21 Michael Meissner PR target/40671 diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index dfc7029..a36e9d2 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #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 +293,11 @@ static const char *ia64_invalid_conversion (const_tree, const_tree); 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 +465,8 @@ static const struct attribute_spec ia64_attribute_table[] = #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 +1923,10 @@ ia64_expand_call (rtx retval, rtx addr, rtx nextarg ATTRIBUTE_UNUSED, 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 +3841,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 +3868,21 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain) /* 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 +4039,8 @@ ia64_function_arg_words (tree type, enum machine_mode mode) 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 +4065,24 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, 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 +4172,15 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, } 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 +4273,22 @@ ia64_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, 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 +4302,12 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, /* 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 +4350,13 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, 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 +4501,11 @@ ia64_return_in_memory (const_tree valtype, const_tree fntype ATTRIBUTE_UNUSED) /* 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 +4576,10 @@ ia64_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) 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 +5388,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 +9915,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 +10034,10 @@ ia64_asm_output_external (FILE *file, tree decl, const char *name) 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 +10140,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. */ @@ -10299,7 +10406,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)); } @@ -10564,6 +10672,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 --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index ff02f75..f91e639 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -73,6 +73,8 @@ extern unsigned int ia64_section_threshold; #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 --git a/gcc/config/ia64/vms.h b/gcc/config/ia64/vms.h index da47320..279586c 100644 --- a/gcc/config/ia64/vms.h +++ b/gcc/config/ia64/vms.h @@ -66,26 +66,6 @@ along with GCC; see the file COPYING3. If not see #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 -- 2.7.4