},
};
+/* Machine-specific symbol_ref flags. */
+#define SYMBOL_FLAG_NEAR (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_FLAG_SAMEGP (SYMBOL_FLAG_MACH_DEP << 1)
+
/* Declarations of static functions. */
static bool alpha_function_ok_for_sibcall
PARAMS ((tree, tree));
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
#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));
/* Otherwise, encode_section_info recorded whether we are to treat
this symbol as having the same GP. */
- return SYMBOL_REF_FLAG (op);
+ return (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_SAMEGP) != 0;
}
/* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr. */
rtx op;
enum machine_mode mode;
{
+ bool is_near;
+
/* Must share the same GP. */
if (!samegp_function_operand (op, mode))
return 0;
if (!TARGET_PROFILING_NEEDS_GP && profile_flag)
return 0;
+ is_near = (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_NEAR) != 0;
+
/* Must be "near" so that the branch is assumed to reach. With
-msmall-text, this is true of all local symbols. */
if (TARGET_SMALL_TEXT)
- return op->jump;
+ return is_near;
/* 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);
+ return is_near && decl_in_text_section (cfun->decl);
}
/* 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 (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. */
static void
alpha_encode_section_info (decl, first)
tree decl;
- int first ATTRIBUTE_UNUSED;
+ int first;
{
- 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);
-
+ default_encode_section_info (decl, first);
+
if (TREE_CODE (decl) == FUNCTION_DECL)
{
+ rtx symbol = XEXP (DECL_RTL (decl), 0);
+ int flags = SYMBOL_REF_FLAGS (symbol);
+
/* 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;
+ if (flags & SYMBOL_FLAG_LOCAL)
+ flags |= SYMBOL_FLAG_NEAR;
}
else
{
Delay marking public functions until they are emitted; otherwise
we don't know that they exist in this unit of translation. */
+ /* Now we *DO* have access to SYMBOL_REF_DECL. Fixme. */
if (!TREE_PUBLIC (decl) && decl_in_text_section (decl))
- symbol->jump = 1;
+ flags |= SYMBOL_FLAG_NEAR;
}
/* 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;
+ flags |= SYMBOL_FLAG_SAMEGP;
- 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);
+ SYMBOL_REF_FLAGS (symbol) = flags;
}
}
-/* 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++);
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 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;
}
#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
void
alpha_setup_incoming_varargs(cum, mode, type, pretend_size, no_rtl)
CUMULATIVE_ARGS cum;
- enum machine_mode mode;
- tree type;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
int *pretend_size;
int no_rtl;
{
and the other its replacement, at the start of a routine. */
HOST_WIDE_INT
-alpha_initial_elimination_offset(from, to)
- unsigned int from, to;
+alpha_initial_elimination_offset (from, to)
+ unsigned int from, to ATTRIBUTE_UNUSED;
{
HOST_WIDE_INT ret;
if ((*targetm.binds_local_p) (decl))
{
rtx symbol = XEXP (DECL_RTL (decl), 0);
+ int flags = SYMBOL_REF_FLAGS (symbol);
/* 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;
+ flags |= SYMBOL_FLAG_NEAR;
/* 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;
+ flags |= SYMBOL_FLAG_SAMEGP;
+
+ SYMBOL_REF_FLAGS (symbol) = flags;
}
/* Output jump tables and the static subroutine information block. */
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)
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)
/* 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;