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.
5 This file is part of GCC.
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)
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.
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/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
33 #include "langhooks.h"
36 /* Return string which is the function name, identified by ID, modified
37 with PREFIX and a suffix consisting of an atsign (@) followed by the
38 number of bytes of arguments. If ID is NULL use the DECL_NAME as base.
39 Return NULL if no change required. */
42 gen_stdcall_or_fastcall_decoration (tree decl
, tree id
, char prefix
)
44 unsigned HOST_WIDE_INT total
= 0;
45 const char *old_str
= IDENTIFIER_POINTER (id
!= NULL_TREE
? id
: DECL_NAME (decl
));
47 tree type
= TREE_TYPE (decl
);
49 if (prototype_p (type
))
52 function_args_iterator args_iter
;
54 /* This attribute is ignored for variadic functions. */
58 /* Quit if we hit an incomplete type. Error is reported
59 by convert_arguments in c-typeck.c or cp/typeck.c. */
60 FOREACH_FUNCTION_ARGS(type
, arg
, args_iter
)
62 HOST_WIDE_INT parm_size
;
63 unsigned HOST_WIDE_INT parm_boundary_bytes
;
65 if (! COMPLETE_TYPE_P (arg
))
68 parm_size
= int_size_in_bytes (arg
);
72 parm_boundary_bytes
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
74 /* Must round up to include padding. This is done the same
75 way as in store_one_arg. */
76 total
+= (parm_size
+ parm_boundary_bytes
- 1)
77 / parm_boundary_bytes
* parm_boundary_bytes
;
81 new_str
= XALLOCAVEC (char, 1 + strlen (old_str
) + 1 + 10 + 1);
82 sprintf (new_str
, "%c%s@" HOST_WIDE_INT_PRINT_UNSIGNED
,
83 prefix
, old_str
, total
);
85 return get_identifier (new_str
);
88 /* Return string which is the function name, identified by ID, modified
89 with an _n@ prefix (where n represents the number of arguments passed in
90 registers). If ID is NULL use the DECL_NAME as base.
91 Return NULL if no change required. */
94 gen_regparm_prefix (tree decl
, tree id
, unsigned int nregs
)
96 unsigned HOST_WIDE_INT total
= 0;
97 const char *old_str
= IDENTIFIER_POINTER (id
!= NULL_TREE
? id
: DECL_NAME (decl
));
99 tree type
= TREE_TYPE (decl
);
101 if (prototype_p (type
))
104 function_args_iterator args_iter
;
106 /* This attribute is ignored for variadic functions. */
110 /* Quit if we hit an incomplete type. Error is reported
111 by convert_arguments in c-typeck.c or cp/typeck.c. */
112 FOREACH_FUNCTION_ARGS(type
, arg
, args_iter
)
114 HOST_WIDE_INT parm_size
;
115 unsigned HOST_WIDE_INT parm_boundary_bytes
;
117 if (! COMPLETE_TYPE_P (arg
))
120 parm_size
= int_size_in_bytes (arg
);
124 parm_boundary_bytes
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
126 /* Must round up to include padding. This is done the same
127 way as in store_one_arg. */
128 total
+= (parm_size
+ parm_boundary_bytes
- 1)
129 / parm_boundary_bytes
* parm_boundary_bytes
;
133 if (nregs
> total
/ UNITS_PER_WORD
)
134 nregs
= total
/ UNITS_PER_WORD
;
135 gcc_assert (nregs
<= 9);
136 new_str
= XALLOCAVEC (char, 3 + strlen (old_str
) + 1);
137 sprintf (new_str
, "_%u@%s", nregs
, old_str
);
139 return get_identifier (new_str
);
142 /* Maybe decorate and get a new identifier for the DECL of a stdcall or
143 fastcall function. The original identifier is supplied in ID. */
146 i386_nlm_maybe_mangle_decl_assembler_name (tree decl
, tree id
)
148 tree type_attributes
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
151 if (lookup_attribute ("stdcall", type_attributes
))
152 new_id
= gen_stdcall_or_fastcall_decoration (decl
, id
, '_');
153 else if (lookup_attribute ("fastcall", type_attributes
))
154 new_id
= gen_stdcall_or_fastcall_decoration (decl
, id
, FASTCALL_PREFIX
);
155 else if ((new_id
= lookup_attribute ("regparm", type_attributes
)))
156 new_id
= gen_regparm_prefix (decl
, id
,
157 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (new_id
))));
164 /* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
165 in the language-independent default hook
166 langhooks.c:lhd_set_decl_assembler_name ()
167 and in cp/mangle.c:mangle_decl (). */
169 i386_nlm_mangle_decl_assembler_name (tree decl
, tree id
)
171 tree new_id
= TREE_CODE (decl
) == FUNCTION_DECL
172 ? i386_nlm_maybe_mangle_decl_assembler_name (decl
, id
)
175 return (new_id
? new_id
: id
);
179 i386_nlm_encode_section_info (tree decl
, rtx rtl
, int first
)
181 default_encode_section_info (decl
, rtl
, first
);
183 if (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 /* FIXME: Imported stdcall names are not modified by the Ada frontend.
189 Check and decorate the RTL name now. */
190 && strcmp (lang_hooks
.name
, "GNU Ada") == 0)
192 rtx symbol
= XEXP (rtl
, 0);
194 tree old_id
= DECL_ASSEMBLER_NAME (decl
);
196 gcc_assert (GET_CODE (symbol
) == SYMBOL_REF
);
198 if ((new_id
= i386_nlm_maybe_mangle_decl_assembler_name (decl
, old_id
)))
199 XSTR (symbol
, 0) = IDENTIFIER_POINTER (new_id
);
203 /* Strip the stdcall/fastcall/regparm pre-/suffix. */
206 i386_nlm_strip_name_encoding (const char *str
)
208 const char *name
= default_strip_name_encoding (str
);
210 if (*str
!= '*' && (*name
== '_' || *name
== '@'))
212 const char *p
= strchr (name
+ 1, '@');
218 name
= ggc_alloc_string (name
, p
- name
);
221 gcc_assert (ISDIGIT (*name
));
223 gcc_assert (name
== p
);