/* The alias set for prologue/epilogue register save/restore. */
-static int alpha_sr_alias_set;
+static GTY(()) int alpha_sr_alias_set;
/* The assembler name of the current function. */
static const char *alpha_fnname;
/* The next explicit relocation sequence number. */
+extern GTY(()) int alpha_next_sequence_number;
int alpha_next_sequence_number = 1;
/* The literal and gpdisp sequence numbers for this insn, as printed
by %# and %* respectively. */
+extern GTY(()) int alpha_this_literal_sequence_number;
+extern GTY(()) int alpha_this_gpdisp_sequence_number;
int alpha_this_literal_sequence_number;
int alpha_this_gpdisp_sequence_number;
+/* Costs of various operations on the different architectures. */
+
+struct alpha_rtx_cost_data
+{
+ unsigned char fp_add;
+ unsigned char fp_mult;
+ unsigned char fp_div_sf;
+ unsigned char fp_div_df;
+ unsigned char int_mult_si;
+ unsigned char int_mult_di;
+ unsigned char int_shift;
+ unsigned char int_cmov;
+};
+
+static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] =
+{
+ { /* EV4 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (6), /* fp_mult */
+ COSTS_N_INSNS (34), /* fp_div_sf */
+ COSTS_N_INSNS (63), /* fp_div_df */
+ COSTS_N_INSNS (23), /* int_mult_si */
+ COSTS_N_INSNS (23), /* int_mult_di */
+ COSTS_N_INSNS (2), /* int_shift */
+ COSTS_N_INSNS (2), /* int_cmov */
+ },
+ { /* EV5 */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult */
+ COSTS_N_INSNS (15), /* fp_div_sf */
+ COSTS_N_INSNS (22), /* fp_div_df */
+ COSTS_N_INSNS (8), /* int_mult_si */
+ COSTS_N_INSNS (12), /* int_mult_di */
+ COSTS_N_INSNS (1) + 1, /* int_shift */
+ COSTS_N_INSNS (1), /* int_cmov */
+ },
+ { /* EV6 */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult */
+ COSTS_N_INSNS (12), /* fp_div_sf */
+ COSTS_N_INSNS (15), /* fp_div_df */
+ COSTS_N_INSNS (7), /* int_mult_si */
+ COSTS_N_INSNS (7), /* int_mult_di */
+ COSTS_N_INSNS (1), /* int_shift */
+ COSTS_N_INSNS (2), /* int_cmov */
+ },
+};
+
/* Declarations of static functions. */
static bool alpha_function_ok_for_sibcall
PARAMS ((tree, tree));
PARAMS ((rtx, enum machine_mode, int, int));
static enum tls_model tls_symbolic_operand_type
PARAMS ((rtx));
-static bool decl_in_text_section
- PARAMS ((tree));
static bool decl_has_samegp
PARAMS ((tree));
static bool alpha_in_small_data_p
PARAMS ((tree));
-static void alpha_encode_section_info
- PARAMS ((tree, int));
-static const char *alpha_strip_name_encoding
- PARAMS ((const char *));
+static rtx get_tls_get_addr
+ PARAMS ((void));
static int some_small_symbolic_operand_1
PARAMS ((rtx *, void *));
static int split_small_symbolic_operand_1
PARAMS ((rtx *, void *));
+static bool alpha_cannot_copy_insn_p
+ PARAMS ((rtx));
+static bool alpha_rtx_costs
+ PARAMS ((rtx, int, int, int *));
static void alpha_set_memflags_1
PARAMS ((rtx, int, int, int));
static rtx alpha_emit_set_const_1
PARAMS ((tree, rtx, rtx, enum machine_mode, int));
static void alpha_sa_mask
PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
-static int find_lo_sum
+static int find_lo_sum_using_gp
PARAMS ((rtx *, void *));
static int alpha_does_function_need_gp
PARAMS ((void));
PARAMS ((void));
static int alpha_multipass_dfa_lookahead
PARAMS ((void));
+static void alpha_reorg
+ PARAMS ((void));
#ifdef OBJECT_FORMAT_ELF
static void alpha_elf_select_rtx_section
#if TARGET_ABI_OPEN_VMS
static bool alpha_linkage_symbol_p
PARAMS ((const char *symname));
+static int alpha_write_one_linkage
+ PARAMS ((splay_tree_node, void *));
static void alpha_write_linkage
PARAMS ((FILE *, const char *, tree));
#endif
#undef TARGET_IN_SMALL_DATA_P
#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding
#if TARGET_ABI_UNICOSMK
static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p
#if TARGET_ABI_OSF
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
#endif
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS alpha_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST hook_int_rtx_0
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Parse target option strings. */
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) != SYMBOL_REF)
- return 0;
+ return false;
/* Easy test for recursion. */
if (op == XEXP (DECL_RTL (current_function_decl), 0))
- return 1;
+ return true;
- /* Otherwise, encode_section_info recorded whether we are to treat
- this symbol as having the same GP. */
- return SYMBOL_REF_FLAG (op);
+ /* Functions that are not local can be overridden, and thus may
+ not share the same gp. */
+ if (! SYMBOL_REF_LOCAL_P (op))
+ return false;
+
+ /* If -msmall-data is in effect, assume that there is only one GP
+ for the module, and so any local symbol has this property. We
+ need explicit relocations to be able to enforce this for symbols
+ not defined in this unit of translation, however. */
+ if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
+ return true;
+
+ /* Functions that are not external are defined in this UoT,
+ and thus must share the same gp. */
+ return ! SYMBOL_REF_EXTERNAL_P (op);
}
/* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr. */
rtx op;
enum machine_mode mode;
{
+ tree op_decl, cfun_sec, op_sec;
+
/* Must share the same GP. */
if (!samegp_function_operand (op, mode))
- return 0;
+ return false;
/* If profiling is implemented via linker tricks, we can't jump
to the nogp alternate entry point. Note that current_function_profile
but is approximately correct for the OSF ABIs. Don't know
what to do for VMS, NT, or UMK. */
if (!TARGET_PROFILING_NEEDS_GP && profile_flag)
- return 0;
+ return false;
+ /* Must be a function. In some cases folks create thunks in static
+ data structures and then make calls to them. If we allow the
+ direct call, we'll get an error from the linker about !samegp reloc
+ against a symbol without a .prologue directive. */
+ if (!SYMBOL_REF_FUNCTION_P (op))
+ return false;
+
/* Must be "near" so that the branch is assumed to reach. With
- -msmall-text, this is true of all local symbols. */
+ -msmall-text, this is assumed true of all local symbols. Since
+ we've already checked samegp, locality is already assured. */
if (TARGET_SMALL_TEXT)
- return op->jump;
+ return true;
+
+ /* Otherwise, a decl is "near" if it is defined in the same section. */
+ if (flag_function_sections)
+ return false;
+
+ op_decl = SYMBOL_REF_DECL (op);
+ if (DECL_ONE_ONLY (current_function_decl)
+ || (op_decl && DECL_ONE_ONLY (op_decl)))
+ return false;
- /* Otherwise, a decl is "near" if it is defined in the same section.
- See alpha_encode_section_info for commentary. */
- return op->jump && decl_in_text_section (cfun->decl);
+ cfun_sec = DECL_SECTION_NAME (current_function_decl);
+ op_sec = op_decl ? DECL_SECTION_NAME (op_decl) : NULL;
+ return ((!cfun_sec && !op_sec)
+ || (cfun_sec && op_sec
+ && strcmp (TREE_STRING_POINTER (cfun_sec),
+ TREE_STRING_POINTER (op_sec)) == 0));
}
/* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
rtx op;
enum machine_mode mode;
{
- const char *str;
-
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- /* Easy pickings. */
- if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op))
- return 1;
-
- /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
- run into problems with the rtl inliner in that the symbol was
- once external, but is local after inlining, which results in
- unrecognizable insns. */
-
- str = XSTR (op, 0);
-
- /* If @[LS], then alpha_encode_section_info sez it's local. */
- if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S'))
- return 1;
-
- /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */
- if (str[0] == '*' && str[1] == '$')
- return 1;
-
- return 0;
+ return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
}
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- const char *str;
-
if (! TARGET_SMALL_DATA)
return 0;
if (GET_CODE (op) != SYMBOL_REF)
return 0;
+ /* ??? There's no encode_section_info equivalent for the rtl
+ constant pool, so SYMBOL_FLAG_SMALL never gets set. */
if (CONSTANT_POOL_ADDRESS_P (op))
- return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
- else
- {
- str = XSTR (op, 0);
- return str[0] == '@' && str[1] == 'S';
- }
+ return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+
+ return (SYMBOL_REF_LOCAL_P (op)
+ && SYMBOL_REF_SMALL_P (op)
+ && SYMBOL_REF_TLS_MODEL (op) == 0);
}
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
rtx op;
enum machine_mode mode;
{
- const char *str;
-
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- if (local_symbolic_operand (op, mode))
- return 0;
-
- /* Also verify that it's not a TLS symbol. */
- str = XSTR (op, 0);
- return str[0] != '%' && str[0] != '@';
+ return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
}
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
enum machine_mode mode;
int size, unspec;
{
- const char *str;
-
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- str = XSTR (op, 0);
- if (str[0] == '%')
+ if (SYMBOL_REF_LOCAL_P (op))
{
- if (size != 64)
+ if (alpha_tls_size > size)
return 0;
}
- else if (str[0] == '@')
+ else
{
- if (alpha_tls_size > size)
+ if (size != 64)
return 0;
}
- else
- return 0;
- switch (str[1])
+ switch (SYMBOL_REF_TLS_MODEL (op))
{
- case 'D':
+ case TLS_MODEL_LOCAL_DYNAMIC:
return unspec == UNSPEC_DTPREL;
- case 'T':
+ case TLS_MODEL_INITIAL_EXEC:
return unspec == UNSPEC_TPREL && size == 64;
- case 't':
- return unspec == UNSPEC_TPREL && size < 64;
+ case TLS_MODEL_LOCAL_EXEC:
+ return unspec == UNSPEC_TPREL;
default:
abort ();
}
tls_symbolic_operand_type (symbol)
rtx symbol;
{
- const char *str;
+ enum tls_model model;
if (GET_CODE (symbol) != SYMBOL_REF)
return 0;
- str = XSTR (symbol, 0);
+ model = SYMBOL_REF_TLS_MODEL (symbol);
- if (str[0] == '%')
- {
- /* ??? Be prepared for -ftls-model=local-dynamic. Perhaps we shouldn't
- have separately encoded local-ness. On well, maybe the user will use
- attribute visibility next time. At least we don't crash... */
- if (str[1] == 'G' || str[1] == 'D')
- return TLS_MODEL_GLOBAL_DYNAMIC;
- if (str[1] == 'T')
- return TLS_MODEL_INITIAL_EXEC;
- }
- else if (str[0] == '@')
- {
- if (str[1] == 'D')
- {
- /* Local dynamic is a waste if we're not going to combine
- the __tls_get_addr calls. So avoid it if not optimizing. */
- if (optimize)
- return TLS_MODEL_LOCAL_DYNAMIC;
- else
- return TLS_MODEL_GLOBAL_DYNAMIC;
- }
- if (str[1] == 'T')
- return TLS_MODEL_INITIAL_EXEC;
- if (str[1] == 't')
- return TLS_MODEL_LOCAL_EXEC;
- }
+ /* Local-exec with a 64-bit size is the same code as initial-exec. */
+ if (model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64)
+ model = TLS_MODEL_INITIAL_EXEC;
- return 0;
+ return model;
}
-
\f
-/* Return true if the function DECL will be placed in the default text
- section. */
-/* ??? Ideally we'd be able to always move from a SYMBOL_REF back to the
- decl, as that would allow us to determine if two functions are in the
- same section, which is what we really want to know. */
-
-static bool
-decl_in_text_section (decl)
- tree decl;
-{
- return (DECL_SECTION_NAME (decl) == NULL_TREE
- && ! (flag_function_sections
- || (targetm.have_named_sections
- && DECL_ONE_ONLY (decl))));
-}
-
/* Return true if the function DECL will share the same GP as any
function in the current unit of translation. */
/* If this is an incomplete type with size 0, then we can't put it
in sdata because it might be too big when completed. */
- if (size > 0 && size <= g_switch_value)
+ if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
return true;
}
return false;
}
-/* If we are referencing a function that is static, make the SYMBOL_REF
- special. We use this to see indicate we can branch to this function
- without setting PV or restoring GP.
-
- If this is a variable that is known to be defined locally, add "@v"
- to the name. If in addition the variable is to go in .sdata/.sbss,
- then add "@s" instead. */
-
-static void
-alpha_encode_section_info (decl, first)
- tree decl;
- int first ATTRIBUTE_UNUSED;
-{
- const char *symbol_str;
- bool is_local;
- char encoding = 0;
- rtx rtl, symbol;
-
- rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
-
- /* Careful not to prod global register variables. */
- if (GET_CODE (rtl) != MEM)
- return;
- symbol = XEXP (rtl, 0);
- if (GET_CODE (symbol) != SYMBOL_REF)
- return;
-
- /* A variable is considered "local" if it is defined in this module. */
- is_local = (*targetm.binds_local_p) (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Mark whether the decl is "near" in distance. If -msmall-text is
- in effect, this is trivially true of all local symbols. */
- if (TARGET_SMALL_TEXT)
- {
- if (is_local)
- symbol->jump = 1;
- }
- else
- {
- /* Otherwise, a decl is "near" if it is defined in this same
- section. What we really need is to be able to access the
- target decl of a call from the call_insn pattern, so that
- we can determine if the call is from the same section. We
- can't do that at present, so handle the common case and
- match up .text with .text.
-
- Delay marking public functions until they are emitted; otherwise
- we don't know that they exist in this unit of translation. */
- if (!TREE_PUBLIC (decl) && decl_in_text_section (decl))
- symbol->jump = 1;
- }
-
- /* Indicate whether the target function shares the same GP as any
- function emitted in this unit of translation. */
- if (decl_has_samegp (decl))
- SYMBOL_REF_FLAG (symbol) = 1;
- return;
- }
-
- /* Early out if we're not going to do anything with this data. */
- if (! TARGET_EXPLICIT_RELOCS)
- return;
-
- symbol_str = XSTR (symbol, 0);
-
- /* Care for TLS variables. */
- if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
- {
- switch (decl_tls_model (decl))
- {
- case TLS_MODEL_GLOBAL_DYNAMIC:
- encoding = 'G';
- break;
- case TLS_MODEL_LOCAL_DYNAMIC:
- encoding = 'D';
- break;
- case TLS_MODEL_INITIAL_EXEC:
- encoding = 'T';
- break;
- case TLS_MODEL_LOCAL_EXEC:
- encoding = (alpha_tls_size == 64 ? 'T' : 't');
- break;
- }
- }
- else if (is_local)
- {
- /* Determine if DECL will wind up in .sdata/.sbss. */
- if (alpha_in_small_data_p (decl))
- encoding = 'S';
- else
- encoding = 'L';
- }
-
- /* Finally, encode this into the symbol string. */
- if (encoding)
- {
- char *newstr;
- size_t len;
- char want_prefix = (is_local ? '@' : '%');
- char other_prefix = (is_local ? '%' : '@');
-
- if (symbol_str[0] == want_prefix)
- {
- if (symbol_str[1] == encoding)
- return;
- symbol_str += 2;
- }
- else if (symbol_str[0] == other_prefix)
- symbol_str += 2;
-
- len = strlen (symbol_str) + 1;
- newstr = alloca (len + 2);
-
- newstr[0] = want_prefix;
- newstr[1] = encoding;
- memcpy (newstr + 2, symbol_str, len);
-
- XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
- }
-}
-
-/* Undo the effects of the above. */
-
-static const char *
-alpha_strip_name_encoding (str)
- const char *str;
-{
- if (str[0] == '@' || str[0] == '%')
- str += 2;
- if (str[0] == '*')
- str++;
- return str;
-}
-
#if TARGET_ABI_OPEN_VMS
static bool
alpha_linkage_symbol_p (symname)
return false;
}
+/* Build the SYMBOL_REF for __tls_get_addr. */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr ()
+{
+ if (!tls_get_addr_libfunc)
+ tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+ return tls_get_addr_libfunc;
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address. */
r0 = gen_rtx_REG (Pmode, 0);
r16 = gen_rtx_REG (Pmode, 16);
- tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ tga = get_tls_get_addr ();
dest = gen_reg_rtx (Pmode);
seq = GEN_INT (alpha_next_sequence_number++);
r0 = gen_rtx_REG (Pmode, 0);
r16 = gen_rtx_REG (Pmode, 16);
- tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ tga = get_tls_get_addr ();
scratch = gen_reg_rtx (Pmode);
seq = GEN_INT (alpha_next_sequence_number++);
return 0;
}
+/* Indicate that INSN cannot be duplicated. This is true for any insn
+ that we've marked with gpdisp relocs, since those have to stay in
+ 1-1 correspondence with one another.
+
+ Techinically we could copy them if we could set up a mapping from one
+ sequence number to another, across the set of insns to be duplicated.
+ This seems overly complicated and error-prone since interblock motion
+ from sched-ebb could move one of the pair of insns to a different block. */
+
+static bool
+alpha_cannot_copy_insn_p (insn)
+ rtx insn;
+{
+ rtx pat;
+
+ if (!reload_completed || !TARGET_EXPLICIT_RELOCS)
+ return false;
+
+ if (GET_CODE (insn) != INSN)
+ return false;
+ if (asm_noperands (insn) >= 0)
+ return false;
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) != SET)
+ return false;
+ pat = SET_SRC (pat);
+ if (GET_CODE (pat) == UNSPEC_VOLATILE)
+ {
+ if (XINT (pat, 1) == UNSPECV_LDGP1
+ || XINT (pat, 1) == UNSPECV_PLDGP2)
+ return true;
+ }
+ else if (GET_CODE (pat) == UNSPEC)
+ {
+ if (XINT (pat, 1) == UNSPEC_LDGP2)
+ return true;
+ }
+
+ return false;
+}
+
+
/* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and return the new rtx. */
return NULL_RTX;
}
\f
+/* Compute a (partial) cost for rtx X. Return true if the complete
+ cost has been computed, and false if subexpressions should be
+ scanned. In either case, *TOTAL contains the cost result. */
+
+static bool
+alpha_rtx_costs (x, code, outer_code, total)
+ rtx x;
+ int code, outer_code;
+ int *total;
+{
+ enum machine_mode mode = GET_MODE (x);
+ bool float_mode_p = FLOAT_MODE_P (mode);
+
+ switch (code)
+ {
+ /* If this is an 8-bit constant, return zero since it can be used
+ nearly anywhere with no cost. If it is a valid operand for an
+ ADD or AND, likewise return 0 if we know it will be used in that
+ context. Otherwise, return 2 since it might be used there later.
+ All other constants take at least two insns. */
+ case CONST_INT:
+ if (INTVAL (x) >= 0 && INTVAL (x) < 256)
+ {
+ *total = 0;
+ return true;
+ }
+ /* FALLTHRU */
+
+ case CONST_DOUBLE:
+ if (x == CONST0_RTX (mode))
+ *total = 0;
+ else if ((outer_code == PLUS && add_operand (x, VOIDmode))
+ || (outer_code == AND && and_operand (x, VOIDmode)))
+ *total = 0;
+ else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode))
+ *total = 2;
+ else
+ *total = COSTS_N_INSNS (2);
+ return true;
+
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode))
+ *total = COSTS_N_INSNS (outer_code != MEM);
+ else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode))
+ *total = COSTS_N_INSNS (1 + (outer_code != MEM));
+ else if (tls_symbolic_operand_type (x))
+ /* Estimate of cost for call_pal rduniq. */
+ *total = COSTS_N_INSNS (15);
+ else
+ /* Otherwise we do a load from the GOT. */
+ *total = COSTS_N_INSNS (alpha_memory_latency);
+ return true;
+
+ case PLUS:
+ case MINUS:
+ if (float_mode_p)
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+ else if (GET_CODE (XEXP (x, 0)) == MULT
+ && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
+ {
+ *total = (rtx_cost (XEXP (XEXP (x, 0), 0), outer_code)
+ + rtx_cost (XEXP (x, 1), outer_code) + 2);
+ return true;
+ }
+ return false;
+
+ case MULT:
+ if (float_mode_p)
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_mult;
+ else if (mode == DImode)
+ *total = alpha_rtx_cost_data[alpha_cpu].int_mult_di;
+ else
+ *total = alpha_rtx_cost_data[alpha_cpu].int_mult_si;
+ return false;
+
+ case ASHIFT:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) <= 3)
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+ /* FALLTHRU */
+
+ case ASHIFTRT:
+ case LSHIFTRT:
+ *total = alpha_rtx_cost_data[alpha_cpu].int_shift;
+ return false;
+
+ case IF_THEN_ELSE:
+ if (float_mode_p)
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+ else
+ *total = alpha_rtx_cost_data[alpha_cpu].int_cmov;
+ return false;
+
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ if (!float_mode_p)
+ *total = COSTS_N_INSNS (70); /* ??? */
+ else if (mode == SFmode)
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_div_sf;
+ else
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_div_df;
+ return false;
+
+ case MEM:
+ *total = COSTS_N_INSNS (alpha_memory_latency);
+ return true;
+
+ case NEG:
+ if (! float_mode_p)
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+ /* FALLTHRU */
+
+ case ABS:
+ if (! float_mode_p)
+ {
+ *total = COSTS_N_INSNS (1) + alpha_rtx_cost_data[alpha_cpu].int_cmov;
+ return false;
+ }
+ /* FALLTHRU */
+
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case UNSIGNED_FIX:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+ return false;
+
+ default:
+ return false;
+ }
+}
+\f
/* REF is an alignable memory location. Place an aligned SImode
reference into *PALIGNED_MEM and the number of bits to shift into
*PBITNUM. SCRATCH is a free register for use in reloading out
abort ();
}
- tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func));
+ tmp = gen_rtx_MEM (QImode, init_one_libfunc (func));
tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
const0_rtx, const0_rtx));
CALL_INSN_FUNCTION_USAGE (tmp) = usage;
{
rtx r = get_hard_reg_initial_val (DImode, 29);
if (GET_CODE (r) != MEM)
- r = gen_mem_addressof (r, NULL_TREE);
+ r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true);
return r;
}
{
rtx x = *px;
- if (GET_CODE (x) == SYMBOL_REF)
+ if (GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
{
- const char *str = XSTR (x, 0);
- if (str[0] == '@' && str[1] == 'D')
- {
- cfun->machine->some_ld_name = str;
- return 1;
- }
+ cfun->machine->some_ld_name = XSTR (x, 0);
+ return 1;
}
return 0;
fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
break;
+ case '+':
+ /* Generates a nop after a noreturn call at the very end of the
+ function. */
+ if (next_real_insn (current_output_insn) == 0)
+ fprintf (file, "\n\tnop");
+ break;
+
case '#':
if (alpha_this_literal_sequence_number == 0)
alpha_this_literal_sequence_number = alpha_next_sequence_number++;
}
if (offset)
- {
- fputc ('+', file);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
- }
+ fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
addr = XEXP (addr, 0);
if (GET_CODE (addr) == REG)
else
abort ();
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
- fprintf (file, "($%d)", basereg);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg);
}
\f
/* Emit RTL insns to initialize the variable parts of a trampoline at
}
#ifdef TRANSFER_FROM_TRAMPOLINE
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
+ emit_library_call (init_one_libfunc ("__enable_execute_stack"),
0, VOIDmode, 1, tramp, Pmode);
#endif
return record;
}
+/* Perform any needed actions needed for a function that is receiving a
+ variable number of arguments.
+
+ On the Alpha, we allocate space for all 12 arg registers, but only
+ push those that are remaining. However, if NO registers need to be
+ saved, don't allocate any space. This is not only because we won't
+ need the space, but because AP includes the current_pretend_args_size
+ and we don't want to mess up any ap-relative addresses already made.
+
+ If we are not to use the floating-point registers, save the integer
+ registers where we would put the floating-point registers. This is
+ not the most efficient way to implement varargs with just one register
+ class, but it isn't worth doing anything more efficient in this rare
+ case. */
+
+void
+alpha_setup_incoming_varargs(cum, mode, type, pretend_size, no_rtl)
+ CUMULATIVE_ARGS cum;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+ int *pretend_size;
+ int no_rtl;
+{
+ if (cum >= 6)
+ return;
+
+ if (!no_rtl)
+ {
+ int set = get_varargs_alias_set ();
+ rtx tmp;
+
+ tmp = gen_rtx_MEM (BLKmode,
+ plus_constant (virtual_incoming_args_rtx,
+ (cum + 6) * UNITS_PER_WORD));
+ set_mem_alias_set (tmp, set);
+ move_block_from_reg (16 + cum, tmp, 6 - cum);
+
+ tmp = gen_rtx_MEM (BLKmode,
+ plus_constant (virtual_incoming_args_rtx,
+ cum * UNITS_PER_WORD));
+ set_mem_alias_set (tmp, set);
+ move_block_from_reg (16 + (TARGET_FPREGS ? 32 : 0) + cum, tmp,
+ 6 - cum);
+ }
+ *pretend_size = 12 * UNITS_PER_WORD;
+}
+
void
alpha_va_start (valist, nextarg)
tree valist;
If no integer registers need be stored, then we must subtract 48
in order to account for the integer arg registers which are counted
- in argsize above, but which are not actually stored on the stack. */
+ in argsize above, but which are not actually stored on the stack.
+ Must further be careful here about structures straddling the last
+ integer argument register; that futzes with pretend_args_size,
+ which changes the meaning of AP. */
if (NUM_ARGS <= 6)
offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
else
- offset = -6 * UNITS_PER_WORD;
+ offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size;
if (TARGET_ABI_OPEN_VMS)
{
}
if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
- imask |= (1L << HARD_FRAME_POINTER_REGNUM);
+ imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
/* One for every register we have to save. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
&& (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
{
if (i < 32)
- imask |= (1L << i);
+ imask |= (1UL << i);
else
- fmask |= (1L << (i - 32));
+ fmask |= (1UL << (i - 32));
}
/* We need to restore these for the handler. */
unsigned regno = EH_RETURN_DATA_REGNO (i);
if (regno == INVALID_REGNUM)
break;
- imask |= 1L << regno;
+ imask |= 1UL << regno;
}
/* If any register spilled, then spill the return address also. */
/* ??? This is required by the Digital stack unwind specification
and isn't needed if we're doing Dwarf2 unwinding. */
if (imask || fmask || alpha_ra_ever_killed ())
- imask |= (1L << REG_RA);
+ imask |= (1UL << REG_RA);
*imaskP = imask;
*fmaskP = fmask;
return sa_size * 8;
}
+/* Define the offset between two registers, one to be eliminated,
+ and the other its replacement, at the start of a routine. */
+
+HOST_WIDE_INT
+alpha_initial_elimination_offset (from, to)
+ unsigned int from, to ATTRIBUTE_UNUSED;
+{
+ HOST_WIDE_INT ret;
+
+ ret = alpha_sa_size ();
+ ret += ALPHA_ROUND (current_function_outgoing_args_size);
+
+ if (from == FRAME_POINTER_REGNUM)
+ ;
+ else if (from == ARG_POINTER_REGNUM)
+ ret += (ALPHA_ROUND (get_frame_size ()
+ + current_function_pretend_args_size)
+ - current_function_pretend_args_size);
+ else
+ abort ();
+
+ return ret;
+}
+
int
alpha_pv_save_size ()
{
#endif
static int
-find_lo_sum (px, data)
+find_lo_sum_using_gp (px, data)
rtx *px;
void *data ATTRIBUTE_UNUSED;
{
- return GET_CODE (*px) == LO_SUM;
+ return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx;
+}
+
+int
+alpha_find_lo_sum_using_gp (insn)
+ rtx insn;
+{
+ return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0;
}
static int
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER)
- {
- enum attr_type type = get_attr_type (insn);
- if (type == TYPE_LDSYM || type == TYPE_JSR)
- return 1;
- if (TARGET_EXPLICIT_RELOCS
- && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0)
- return 1;
- }
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && get_attr_usegp (insn))
+ return 1;
return 0;
}
}
/* Save register RA next. */
- if (imask & (1L << REG_RA))
+ if (imask & (1UL << REG_RA))
{
mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
set_mem_alias_set (mem, alpha_sr_alias_set);
FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
- imask &= ~(1L << REG_RA);
+ imask &= ~(1UL << REG_RA);
reg_offset += 8;
}
/* Now save any other registers required to be saved. */
for (i = 0; i < 32; i++)
- if (imask & (1L << i))
+ if (imask & (1UL << i))
{
mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
set_mem_alias_set (mem, alpha_sr_alias_set);
}
for (i = 0; i < 32; i++)
- if (fmask & (1L << i))
+ if (fmask & (1UL << i))
{
mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
set_mem_alias_set (mem, alpha_sr_alias_set);
reg_offset = -56;
for (i = 9; i < 15; i++)
- if (imask & (1L << i))
+ if (imask & (1UL << i))
{
mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
reg_offset));
reg_offset -= 8;
}
for (i = 2; i < 10; i++)
- if (fmask & (1L << i))
+ if (fmask & (1UL << i))
{
mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
reg_offset));
/* If we have to allocate space for outgoing args, do it now. */
if (current_function_outgoing_args_size != 0)
- FRP (emit_move_insn
- (stack_pointer_rtx,
- plus_constant (hard_frame_pointer_rtx,
- - (ALPHA_ROUND
- (current_function_outgoing_args_size)))));
+ {
+ rtx seq
+ = emit_move_insn (stack_pointer_rtx,
+ plus_constant
+ (hard_frame_pointer_rtx,
+ - (ALPHA_ROUND
+ (current_function_outgoing_args_size))));
+
+ /* Only set FRAME_RELATED_P on the stack adjustment we just emitted
+ if ! frame_pointer_needed. Setting the bit will change the CFA
+ computation rule to use sp again, which would be wrong if we had
+ frame_pointer_needed, as this means sp might move unpredictably
+ later on.
+
+ Also, note that
+ frame_pointer_needed
+ => vms_unwind_regno == HARD_FRAME_POINTER_REGNUM
+ and
+ current_function_outgoing_args_size != 0
+ => alpha_procedure_type != PT_NULL,
+
+ so when we are not setting the bit here, we are guaranteed to
+ have emited an FRP frame pointer update just before. */
+ RTX_FRAME_RELATED_P (seq) = ! frame_pointer_needed;
+ }
}
else if (!TARGET_ABI_UNICOSMK)
{
/* Stack space needed for pushing registers clobbered by us. */
HOST_WIDE_INT sa_size;
/* Complete stack size needed. */
- HOST_WIDE_INT frame_size;
+ unsigned HOST_WIDE_INT frame_size;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
char *entry_label = (char *) alloca (strlen (fnname) + 6);
if (TARGET_ABI_UNICOSMK)
;
else if (TARGET_ABI_OPEN_VMS)
- {
- fprintf (file, "\t.frame $%d,", vms_unwind_regno);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- frame_size >= ((HOST_WIDE_INT) 1 << 31) ? 0 : frame_size);
- fputs (",$26,", file);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
- fputs ("\n", file);
- }
+ fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
+ HOST_WIDE_INT_PRINT_DEC "\n",
+ vms_unwind_regno,
+ frame_size >= (1UL << 31) ? 0 : frame_size,
+ reg_offset);
else if (!flag_inhibit_size_directive)
- {
- fprintf (file, "\t.frame $%d,",
- (frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- frame_size >= (1l << 31) ? 0 : frame_size);
- fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
- }
+ fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
+ (frame_pointer_needed
+ ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM),
+ frame_size >= (1UL << 31) ? 0 : frame_size,
+ current_function_pretend_args_size);
/* Describe which registers were spilled. */
if (TARGET_ABI_UNICOSMK)
if (imask)
/* ??? Does VMS care if mask contains ra? The old code didn't
set it, so I don't here. */
- fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
+ fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1UL << REG_RA));
if (fmask)
fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
if (alpha_procedure_type == PT_REGISTER)
{
if (imask)
{
- fprintf (file, "\t.mask 0x%lx,", imask);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
- putc ('\n', file);
+ fprintf (file, "\t.mask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", imask,
+ frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size);
for (i = 0; i < 32; ++i)
- if (imask & (1L << i))
+ if (imask & (1UL << i))
reg_offset += 8;
}
if (fmask)
- {
- fprintf (file, "\t.fmask 0x%lx,", fmask);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
- putc ('\n', file);
- }
+ fprintf (file, "\t.fmask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", fmask,
+ frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size);
}
#if TARGET_ABI_OPEN_VMS
FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
reg_offset += 8;
- imask &= ~(1L << REG_RA);
+ imask &= ~(1UL << REG_RA);
for (i = 0; i < 32; ++i)
- if (imask & (1L << i))
+ if (imask & (1UL << i))
{
if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
fp_offset = reg_offset;
}
for (i = 0; i < 32; ++i)
- if (fmask & (1L << i))
+ if (fmask & (1UL << i))
{
mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
set_mem_alias_set (mem, alpha_sr_alias_set);
reg_offset = -56;
for (i = 9; i < 15; i++)
- if (imask & (1L << i))
+ if (imask & (1UL << i))
{
mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
reg_offset));
}
for (i = 2; i < 10; i++)
- if (fmask & (1L << i))
+ if (fmask & (1UL << i))
{
mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
reg_offset));
}
}
\f
-#if TARGET_ABI_OPEN_VMS
-#include <splay-tree.h>
-
-/* Structure to collect function names for final output
- in link section. */
-
-enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
-enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
-
-struct alpha_funcs
-{
- int num;
- splay_tree links;
-};
-
-struct alpha_links
-{
- int num;
- rtx linkage;
- enum links_kind lkind;
- enum reloc_kind rkind;
-};
-
-static splay_tree alpha_funcs_tree;
-static splay_tree alpha_links_tree;
-
-static int mark_alpha_links_node PARAMS ((splay_tree_node, void *));
-static void mark_alpha_links PARAMS ((void *));
-static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *));
-
-static int alpha_funcs_num;
-#endif
-
/* Output the rest of the textual info surrounding the epilogue. */
void
alpha_end_function (file, fnname, decl)
FILE *file;
const char *fnname;
- tree decl;
+ tree decl ATTRIBUTE_UNUSED;
{
/* End the function. */
if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
alpha_write_linkage (file, fnname, decl);
#endif
- /* Show that we know this function if it is called again.
- This is only meaningful for symbols that bind locally. */
- if ((*targetm.binds_local_p) (decl))
- {
- rtx symbol = XEXP (DECL_RTL (decl), 0);
-
- /* Mark whether the decl is "near". See the commentary in
- alpha_encode_section_info wrt the .text section. */
- if (decl_in_text_section (decl))
- symbol->jump = 1;
-
- /* Mark whether the decl shares a GP with other functions
- in this unit of translation. This is trivially true of
- local symbols. */
- SYMBOL_REF_FLAG (symbol) = 1;
- }
-
/* Output jump tables and the static subroutine information block. */
if (TARGET_ABI_UNICOSMK)
{
};
static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int));
-static void alpha_handle_trap_shadows PARAMS ((rtx));
+static void alpha_handle_trap_shadows PARAMS ((void));
/* Summary the effects of expression X on the machine. Update SUM, a pointer
to the summary structure. SET is nonzero if the insn is setting the
(d) The trap shadow may not include any branch instructions. */
static void
-alpha_handle_trap_shadows (insns)
- rtx insns;
+alpha_handle_trap_shadows ()
{
struct shadow_summary shadow;
int trap_pending, exception_nesting;
shadow.used.mem = 0;
shadow.defd = shadow.used;
- for (i = insns; i ; i = NEXT_INSN (i))
+ for (i = get_insns (); i ; i = NEXT_INSN (i))
{
if (GET_CODE (i) == NOTE)
{
static rtx alphaev5_next_nop PARAMS ((int *));
static void alpha_align_insns
- PARAMS ((rtx, unsigned int, rtx (*)(rtx, int *, int *), rtx (*)(int *)));
+ PARAMS ((unsigned int, rtx (*)(rtx, int *, int *), rtx (*)(int *)));
static enum alphaev4_pipe
alphaev4_insn_pipe (insn)
/* The instruction group alignment main loop. */
static void
-alpha_align_insns (insns, max_align, next_group, next_nop)
- rtx insns;
+alpha_align_insns (max_align, next_group, next_nop)
unsigned int max_align;
rtx (*next_group) PARAMS ((rtx, int *, int *));
rtx (*next_nop) PARAMS ((int *));
rtx i, next;
/* Let shorten branches care for assigning alignments to code labels. */
- shorten_branches (insns);
+ shorten_branches (get_insns ());
if (align_functions < 4)
align = 4;
align = max_align;
ofs = prev_in_use = 0;
- i = insns;
+ i = get_insns ();
if (GET_CODE (i) == NOTE)
i = next_nonnote_insn (i);
\f
/* Machine dependent reorg pass. */
-void
-alpha_reorg (insns)
- rtx insns;
+static void
+alpha_reorg ()
{
if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
- alpha_handle_trap_shadows (insns);
+ alpha_handle_trap_shadows ();
/* Due to the number of extra trapb insns, don't bother fixing up
alignment when trap precision is instruction. Moreover, we can
&& flag_schedule_insns_after_reload)
{
if (alpha_cpu == PROCESSOR_EV4)
- alpha_align_insns (insns, 8, alphaev4_next_group, alphaev4_next_nop);
+ alpha_align_insns (8, alphaev4_next_group, alphaev4_next_nop);
else if (alpha_cpu == PROCESSOR_EV5)
- alpha_align_insns (insns, 16, alphaev5_next_group, alphaev5_next_nop);
+ alpha_align_insns (16, alphaev5_next_group, alphaev5_next_nop);
}
}
\f
#endif /* OBJECT_FORMAT_ELF */
\f
-/* Structure to collect function names for final output
- in link section. */
+/* Structure to collect function names for final output in link section. */
+/* Note that items marked with GTY can't be ifdef'ed out. */
enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
struct alpha_links GTY(())
{
+ int num;
rtx linkage;
- enum links_kind kind;
+ enum links_kind lkind;
+ enum reloc_kind rkind;
+};
+
+struct alpha_funcs GTY(())
+{
+ int num;
+ splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+ links;
};
static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
- splay_tree alpha_links;
+ splay_tree alpha_links_tree;
+static GTY ((param1_is (tree), param2_is (struct alpha_funcs *)))
+ splay_tree alpha_funcs_tree;
+
+static GTY(()) int alpha_funcs_num;
#if TARGET_ABI_OPEN_VMS
{
splay_tree_node node;
struct alpha_links *al;
- struct alpha_funcs *cfaf;
if (name[0] == '*')
name++;
if (is_local)
{
- alpha_funcs_tree = splay_tree_new
- ((splay_tree_compare_fn) splay_tree_compare_pointers,
- (splay_tree_delete_key_fn) free,
- (splay_tree_delete_key_fn) free);
+ struct alpha_funcs *cfaf;
+
+ if (!alpha_funcs_tree)
+ alpha_funcs_tree = splay_tree_new_ggc ((splay_tree_compare_fn)
+ splay_tree_compare_pointers);
- cfaf = (struct alpha_funcs *) xmalloc (sizeof (struct alpha_funcs));
+ cfaf = (struct alpha_funcs *) ggc_alloc (sizeof (struct alpha_funcs));
cfaf->links = 0;
cfaf->num = ++alpha_funcs_num;
splay_tree_insert (alpha_funcs_tree,
(splay_tree_key) current_function_decl,
(splay_tree_value) cfaf);
-
}
if (alpha_links_tree)
}
}
else
- {
- alpha_links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
- }
+ alpha_links_tree = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
name = ggc_strdup (name);
al = (struct alpha_links *) lnode->value;
}
else
- {
- cfaf->links = splay_tree_new
- ((splay_tree_compare_fn) strcmp,
- (splay_tree_delete_key_fn) free,
- (splay_tree_delete_key_fn) free);
- ggc_add_root (&cfaf->links, 1, 1, mark_alpha_links);
- }
+ cfaf->links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
if (!al)
{
name_len = strlen (name);
- al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
+ al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
al->num = cfaf->num;
node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
abort ();
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = alpha_strip_name_encoding (name);
+ name = default_strip_name_encoding (name);
len = strlen (name);
if (TREE_CODE (decl) == FUNCTION_DECL)
mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
set_mem_alias_set (mem, alpha_sr_alias_set);
FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
- (*imaskP) &= ~(1L << REG_RA);
+ (*imaskP) &= ~(1UL << REG_RA);
/* Save the old frame pointer. */
mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
set_mem_alias_set (mem, alpha_sr_alias_set);
FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
- (*imaskP) &= ~(1L << HARD_FRAME_POINTER_REGNUM);
+ (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM);
emit_insn (gen_blockage ());
x = XEXP (x, 0);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
- fnname = alpha_strip_name_encoding (XSTR (x, 0));
+ fnname = default_name_encoding (XSTR (x, 0));
len = strlen (fnname);
if (len + SSIB_PREFIX_LEN > 255)
for (x = machine->first_ciw; x; x = XEXP (x, 1))
{
ciw = XEXP (x, 0);
- fprintf (file, "\t.quad\t");
#if HOST_BITS_PER_WIDE_INT == 32
- fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_DOUBLE_HEX "\n",
CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
#else
- fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (ciw));
+ fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw));
#endif
- fprintf (file, "\n");
}
}
/* List of identifiers for which an extern declaration might have to be
emitted. */
+/* FIXME: needs to use GC, so it can be saved and restored for PCH. */
struct unicosmk_extern_list
{
/* We have to strip the encoding and possibly remove user_label_prefix
from the identifier in order to handle -fleading-underscore and
explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */
- real_name = alpha_strip_name_encoding (p->name);
+ real_name = default_strip_name_encoding (p->name);
if (len && p->name[0] == '*'
&& !memcmp (real_name, user_label_prefix, len))
real_name += len;
/* Structure to collect identifiers which have been replaced by DEX
expressions. */
+/* FIXME: needs to use GC, so it can be saved and restored for PCH. */
struct unicosmk_dex {
struct unicosmk_dex *next;