0
|
1 /* Subroutines for insn-output.c for NetWare.
|
|
2 Contributed by Jan Beulich (jbeulich@novell.com)
|
|
3 Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 GCC is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
|
9 the Free Software Foundation; either version 3, or (at your option)
|
|
10 any later version.
|
|
11
|
|
12 GCC is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GCC; see the file COPYING3. If not see
|
|
19 <http://www.gnu.org/licenses/>. */
|
|
20
|
|
21 #include "config.h"
|
|
22 #include "system.h"
|
|
23 #include "coretypes.h"
|
|
24 #include "tm.h"
|
|
25 #include "rtl.h"
|
|
26 #include "regs.h"
|
|
27 #include "hard-reg-set.h"
|
|
28 #include "output.h"
|
|
29 #include "tree.h"
|
|
30 #include "flags.h"
|
|
31 #include "tm_p.h"
|
|
32 #include "toplev.h"
|
|
33 #include "ggc.h"
|
|
34
|
|
35 /* Return string which is the function name, identified by ID, modified
|
|
36 with PREFIX and a suffix consisting of an atsign (@) followed by the
|
|
37 number of bytes of arguments. If ID is NULL use the DECL_NAME as base.
|
|
38 Return NULL if no change required. */
|
|
39
|
|
40 static tree
|
|
41 gen_stdcall_or_fastcall_decoration (tree decl, tree id, char prefix)
|
|
42 {
|
|
43 unsigned HOST_WIDE_INT total = 0;
|
|
44 const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
|
|
45 char *new_str;
|
|
46 tree type = TREE_TYPE (decl);
|
|
47
|
|
48 if (prototype_p (type))
|
|
49 {
|
|
50 tree arg;
|
|
51 function_args_iterator args_iter;
|
|
52
|
|
53 /* This attribute is ignored for variadic functions. */
|
|
54 if (stdarg_p (type))
|
|
55 return NULL_TREE;
|
|
56
|
|
57 /* Quit if we hit an incomplete type. Error is reported
|
|
58 by convert_arguments in c-typeck.c or cp/typeck.c. */
|
|
59 FOREACH_FUNCTION_ARGS(type, arg, args_iter)
|
|
60 {
|
|
61 HOST_WIDE_INT parm_size;
|
|
62 unsigned HOST_WIDE_INT parm_boundary_bytes;
|
|
63
|
|
64 if (! COMPLETE_TYPE_P (arg))
|
|
65 break;
|
|
66
|
|
67 parm_size = int_size_in_bytes (arg);
|
|
68 if (parm_size < 0)
|
|
69 break;
|
|
70
|
|
71 parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
|
|
72
|
|
73 /* Must round up to include padding. This is done the same
|
|
74 way as in store_one_arg. */
|
|
75 total += (parm_size + parm_boundary_bytes - 1)
|
|
76 / parm_boundary_bytes * parm_boundary_bytes;
|
|
77 }
|
|
78 }
|
|
79
|
|
80 new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 10 + 1);
|
|
81 sprintf (new_str, "%c%s@" HOST_WIDE_INT_PRINT_UNSIGNED,
|
|
82 prefix, old_str, total);
|
|
83
|
|
84 return get_identifier (new_str);
|
|
85 }
|
|
86
|
|
87 /* Return string which is the function name, identified by ID, modified
|
|
88 with an _n@ prefix (where n represents the number of arguments passed in
|
|
89 registers). If ID is NULL use the DECL_NAME as base.
|
|
90 Return NULL if no change required. */
|
|
91
|
|
92 static tree
|
|
93 gen_regparm_prefix (tree decl, tree id, unsigned int nregs)
|
|
94 {
|
|
95 unsigned HOST_WIDE_INT total = 0;
|
|
96 const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
|
|
97 char *new_str;
|
|
98 tree type = TREE_TYPE (decl);
|
|
99
|
|
100 if (prototype_p (type))
|
|
101 {
|
|
102 tree arg;
|
|
103 function_args_iterator args_iter;
|
|
104
|
|
105 /* This attribute is ignored for variadic functions. */
|
|
106 if (stdarg_p (type))
|
|
107 return NULL_TREE;
|
|
108
|
|
109 /* Quit if we hit an incomplete type. Error is reported
|
|
110 by convert_arguments in c-typeck.c or cp/typeck.c. */
|
|
111 FOREACH_FUNCTION_ARGS(type, arg, args_iter)
|
|
112 {
|
|
113 HOST_WIDE_INT parm_size;
|
|
114 unsigned HOST_WIDE_INT parm_boundary_bytes;
|
|
115
|
|
116 if (! COMPLETE_TYPE_P (arg))
|
|
117 break;
|
|
118
|
|
119 parm_size = int_size_in_bytes (arg);
|
|
120 if (parm_size < 0)
|
|
121 break;
|
|
122
|
|
123 parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
|
|
124
|
|
125 /* Must round up to include padding. This is done the same
|
|
126 way as in store_one_arg. */
|
|
127 total += (parm_size + parm_boundary_bytes - 1)
|
|
128 / parm_boundary_bytes * parm_boundary_bytes;
|
|
129 }
|
|
130 }
|
|
131
|
|
132 if (nregs > total / UNITS_PER_WORD)
|
|
133 nregs = total / UNITS_PER_WORD;
|
|
134 gcc_assert (nregs <= 9);
|
|
135 new_str = XALLOCAVEC (char, 3 + strlen (old_str) + 1);
|
|
136 sprintf (new_str, "_%u@%s", nregs, old_str);
|
|
137
|
|
138 return get_identifier (new_str);
|
|
139 }
|
|
140
|
|
141 /* Maybe decorate and get a new identifier for the DECL of a stdcall or
|
|
142 fastcall function. The original identifier is supplied in ID. */
|
|
143
|
|
144 static tree
|
|
145 i386_nlm_maybe_mangle_decl_assembler_name (tree decl, tree id)
|
|
146 {
|
|
147 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
|
|
148 tree new_id;
|
|
149
|
|
150 if (lookup_attribute ("stdcall", type_attributes))
|
|
151 new_id = gen_stdcall_or_fastcall_decoration (decl, id, '_');
|
|
152 else if (lookup_attribute ("fastcall", type_attributes))
|
|
153 new_id = gen_stdcall_or_fastcall_decoration (decl, id, FASTCALL_PREFIX);
|
|
154 else if ((new_id = lookup_attribute ("regparm", type_attributes)))
|
|
155 new_id = gen_regparm_prefix (decl, id,
|
|
156 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (new_id))));
|
|
157 else
|
|
158 new_id = NULL_TREE;
|
|
159
|
|
160 return new_id;
|
|
161 }
|
|
162
|
|
163 /* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
|
|
164 in the language-independent default hook
|
|
165 langhooks.c:lhd_set_decl_assembler_name ()
|
|
166 and in cp/mangle.c:mangle_decl (). */
|
|
167 tree
|
|
168 i386_nlm_mangle_decl_assembler_name (tree decl, tree id)
|
|
169 {
|
|
170 tree new_id = TREE_CODE (decl) == FUNCTION_DECL
|
|
171 ? i386_nlm_maybe_mangle_decl_assembler_name (decl, id)
|
|
172 : NULL_TREE;
|
|
173
|
|
174 return (new_id ? new_id : id);
|
|
175 }
|
|
176
|
|
177 void
|
|
178 i386_nlm_encode_section_info (tree decl, rtx rtl, int first)
|
|
179 {
|
|
180 default_encode_section_info (decl, rtl, first);
|
|
181
|
|
182 if (first
|
|
183 && TREE_CODE (decl) == FUNCTION_DECL
|
|
184 /* Do not change the identifier if a verbatim asmspec
|
|
185 or if stdcall suffix already added. */
|
|
186 && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*'
|
|
187 && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@'))
|
|
188 {
|
|
189 /* FIXME: In Ada, and perhaps other language frontends,
|
|
190 imported stdcall names may not yet have been modified.
|
|
191 Check and do it know. */
|
|
192 rtx symbol = XEXP (rtl, 0);
|
|
193 tree new_id;
|
|
194 tree old_id = DECL_ASSEMBLER_NAME (decl);
|
|
195
|
|
196 gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
|
|
197
|
|
198 if ((new_id = i386_nlm_maybe_mangle_decl_assembler_name (decl, old_id)))
|
|
199 {
|
|
200 /* These attributes must be present on first declaration,
|
|
201 change_decl_assembler_name will warn if they are added
|
|
202 later and the decl has been referenced, but duplicate_decls
|
|
203 should catch the mismatch first. */
|
|
204 change_decl_assembler_name (decl, new_id);
|
|
205 XSTR (symbol, 0) = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
|
206 }
|
|
207 }
|
|
208 }
|
|
209
|
|
210 /* Strip the stdcall/fastcall/regparm pre-/suffix. */
|
|
211
|
|
212 const char *
|
|
213 i386_nlm_strip_name_encoding (const char *str)
|
|
214 {
|
|
215 const char *name = default_strip_name_encoding (str);
|
|
216
|
|
217 if (*str != '*' && (*name == '_' || *name == '@'))
|
|
218 {
|
|
219 const char *p = strchr (name + 1, '@');
|
|
220
|
|
221 if (p)
|
|
222 {
|
|
223 ++name;
|
|
224 if (ISDIGIT (p[1]))
|
|
225 name = ggc_alloc_string (name, p - name);
|
|
226 else
|
|
227 {
|
|
228 gcc_assert (ISDIGIT (*name));
|
|
229 name++;
|
|
230 gcc_assert (name == p);
|
|
231 }
|
|
232 }
|
|
233 }
|
|
234 return name;
|
|
235 }
|
|
236
|
|
237 /* Sometimes certain combinations of command options do not make
|
|
238 sense on a particular target machine. You can define a macro
|
|
239 `OVERRIDE_OPTIONS' to take account of this. This macro, if
|
|
240 defined, is executed once just after all the command options have
|
|
241 been parsed.
|
|
242
|
|
243 Don't use this macro to turn on various extra optimizations for
|
|
244 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
|
|
245
|
|
246 void
|
|
247 netware_override_options (void)
|
|
248 {
|
|
249 override_options ();
|
|
250
|
|
251 if (flag_pic)
|
|
252 {
|
|
253 error ("-fPIC and -fpic are not supported for this target");
|
|
254 flag_pic = 0;
|
|
255 }
|
|
256 }
|