1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
--- gcc/config/arm/arm.c 2003-06-14 15:20:53.000000000 +0100
+++ gcc/config/arm/arm.c 2004-03-06 15:15:32.000000000 +0000
@@ -2364,6 +2394,40 @@
return 1;
}
+/* Return true if OP is a symbolic operand that resolves locally. */
+
+static int
+local_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ op = XEXP (XEXP (op, 0), 0);
+
+ if (GET_CODE (op) == LABEL_REF)
+ return 1;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+
+ /* These we've been told are local by varasm and encode_section_info
+ respectively. */
+ if (CONSTANT_POOL_ADDRESS_P (op) || ENCODED_LOCAL_BINDING_ATTR_P (XSTR (op, 0)))
+ return 1;
+
+ /* There is, however, a not insubstantial body of code in the rest of
+ the compiler that assumes it can just stick the results of
+ ASM_GENERATE_INTERNAL_LABEL in a symbol_ref and have done. */
+ /* ??? This is a hack. Should update the body of the compiler to
+ always create a DECL an invoke targetm.encode_section_info. */
+ if (strncmp (arm_strip_name_encoding (XSTR (op, 0)), ".L", 2) == 0)
+ return 1;
+
+ return 0;
+}
+
rtx
legitimize_pic_address (orig, mode, reg)
rtx orig;
@@ -2404,10 +2468,7 @@
else
emit_insn (gen_pic_load_addr_thumb (address, orig));
- if ((GET_CODE (orig) == LABEL_REF
- || (GET_CODE (orig) == SYMBOL_REF &&
- ENCODED_SHORT_CALL_ATTR_P (XSTR (orig, 0))))
- && NEED_GOT_RELOC)
+ if (local_symbolic_operand (orig, Pmode) && NEED_GOT_RELOC)
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
else
{
@@ -8804,11 +8911,7 @@
if (NEED_GOT_RELOC && flag_pic && making_const_table &&
(GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
{
- if (GET_CODE (x) == SYMBOL_REF
- && (CONSTANT_POOL_ADDRESS_P (x)
- || ENCODED_SHORT_CALL_ATTR_P (XSTR (x, 0))))
- fputs ("(GOTOFF)", asm_out_file);
- else if (GET_CODE (x) == LABEL_REF)
+ if (local_symbolic_operand (x, Pmode))
fputs ("(GOTOFF)", asm_out_file);
else
fputs ("(GOT)", asm_out_file);
@@ -11335,6 +11418,11 @@
else if (! TREE_PUBLIC (decl))
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
}
+
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
+ && flag_pic
+ && (*targetm.binds_local_p) (decl))
+ arm_encode_call_attribute (decl, LOCAL_BINDING_FLAG_CHAR);
}
#endif /* !ARM_PE */
--- gcc/config/arm/arm.h Fri Mar 5 18:49:44 2004
+++ gcc/config/arm/arm.h Fri Mar 5 15:04:31 2004
@@ -1870,6 +1870,7 @@
Note, '@' and '*' have already been taken. */
#define SHORT_CALL_FLAG_CHAR '^'
#define LONG_CALL_FLAG_CHAR '#'
+#define LOCAL_BINDING_FLAG_CHAR '%'
#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
(*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
@@ -1877,6 +1878,9 @@
#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME) \
(*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
+#define ENCODED_LOCAL_BINDING_ATTR_P(SYMBOL_NAME) \
+ (*(SYMBOL_NAME) == LOCAL_BINDING_FLAG_CHAR)
+
#ifndef SUBTARGET_NAME_ENCODING_LENGTHS
#define SUBTARGET_NAME_ENCODING_LENGTHS
#endif
@@ -1888,6 +1892,7 @@
#define ARM_NAME_ENCODING_LENGTHS \
case SHORT_CALL_FLAG_CHAR: return 1; \
case LONG_CALL_FLAG_CHAR: return 1; \
+ case LOCAL_BINDING_FLAG_CHAR: return 1; \
case '*': return 1; \
SUBTARGET_NAME_ENCODING_LENGTHS
|