Merge -r 127928:132243 from trunk
[official-gcc.git] / gcc / config / i386 / netware.c
blob0357baff1692123c0b4b77064372804699716c50
1 /* Subroutines for insn-output.c for NetWare.
2 Contributed by Jan Beulich (jbeulich@novell.com)
3 Copyright (C) 2004, 2005, 2007 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)
10 any later version.
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/>. */
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"
36 /* Return string which is the former assembler name modified with an
37 underscore prefix and a suffix consisting of an atsign (@) followed
38 by the number of bytes of arguments */
40 static tree
41 gen_stdcall_or_fastcall_decoration (tree decl, char prefix)
43 unsigned total = 0;
44 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
45 of DECL_ASSEMBLER_NAME. */
46 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
47 char *newsym;
48 tree type = TREE_TYPE (decl);
49 tree arg;
50 function_args_iterator args_iter;
52 if (prototype_p (type))
54 /* These attributes are ignored for variadic functions in
55 i386.c:ix86_return_pops_args. For compatibility with MS
56 compiler do not add @0 suffix here. */
57 if (stdarg_p (type))
58 return NULL_TREE;
60 /* Quit if we hit an incomplete type. Error is reported
61 by convert_arguments in c-typeck.c or cp/typeck.c. */
62 FOREACH_FUNCTION_ARGS(type, arg, args_iter)
64 unsigned parm_size;
66 if (! COMPLETE_TYPE_P (arg))
67 break;
69 parm_size = int_size_in_bytes (TYPE_SIZE (arg));
70 if (parm_size < 0)
71 break;
73 /* Must round up to include padding. This is done the same
74 way as in store_one_arg. */
75 parm_size = ((parm_size + PARM_BOUNDARY - 1)
76 / PARM_BOUNDARY * PARM_BOUNDARY);
77 total += parm_size;
81 newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1);
82 return get_identifier_with_length (newsym,
83 sprintf (newsym,
84 "%c%s@%u",
85 prefix,
86 asmname,
87 total / BITS_PER_UNIT));
90 /* Return string which is the former assembler name modified with an
91 _n@ prefix where n represents the number of arguments passed in
92 registers */
94 static tree
95 gen_regparm_prefix (tree decl, unsigned nregs)
97 unsigned total = 0;
98 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
99 of DECL_ASSEMBLER_NAME. */
100 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
101 char *newsym;
102 tree type = TREE_TYPE (decl);
103 tree arg;
104 function_args_iterator args_iter;
106 if (prototype_p (type))
108 /* This attribute is ignored for variadic functions. */
109 if (stdarg_p (type))
110 return NULL_TREE;
112 /* Quit if we hit an incomplete type. Error is reported
113 by convert_arguments in c-typeck.c or cp/typeck.c. */
114 FOREACH_FUNCTION_ARGS(type, arg, args_iter)
116 unsigned parm_size;
118 if (! COMPLETE_TYPE_P (arg))
119 break;
121 parm_size = int_size_in_bytes (arg);
122 if (parm_size < 0)
123 break;
125 parm_size = ((parm_size + PARM_BOUNDARY - 1)
126 / PARM_BOUNDARY * PARM_BOUNDARY);
127 total += parm_size;
131 if (nregs > total / BITS_PER_WORD)
132 nregs = total / BITS_PER_WORD;
133 gcc_assert (nregs <= 9);
134 newsym = alloca (3 + strlen (asmname) + 1);
135 return get_identifier_with_length (newsym,
136 sprintf (newsym,
137 "_%u@%s",
138 nregs,
139 asmname));
142 void
143 i386_nlm_encode_section_info (tree decl, rtx rtl, int first)
145 default_encode_section_info (decl, rtl, first);
147 if (first
148 && TREE_CODE (decl) == FUNCTION_DECL
149 && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*'
150 && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@'))
152 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
153 tree newid;
155 if (lookup_attribute ("stdcall", type_attributes))
156 newid = gen_stdcall_or_fastcall_decoration (decl, '_');
157 else if (lookup_attribute ("fastcall", type_attributes))
158 newid = gen_stdcall_or_fastcall_decoration (decl, FASTCALL_PREFIX);
159 else if ((newid = lookup_attribute ("regparm", type_attributes)) != NULL_TREE)
160 newid = gen_regparm_prefix (decl,
161 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (newid))));
162 if (newid != NULL_TREE)
164 rtx rtlname = XEXP (rtl, 0);
166 if (GET_CODE (rtlname) == MEM)
167 rtlname = XEXP (rtlname, 0);
168 XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
169 /* These attributes must be present on first declaration,
170 change_decl_assembler_name will warn if they are added
171 later and the decl has been referenced, but duplicate_decls
172 should catch the mismatch before this is called. */
173 change_decl_assembler_name (decl, newid);
178 /* Strip the stdcall/fastcall/regparm pre-/suffix. */
180 const char *
181 i386_nlm_strip_name_encoding (const char *str)
183 const char *name = default_strip_name_encoding (str);
185 if (*str != '*' && (*name == '_' || *name == '@'))
187 const char *p = strchr (name + 1, '@');
189 if (p)
191 ++name;
192 if (ISDIGIT (p[1]))
193 name = ggc_alloc_string (name, p - name);
194 else
196 gcc_assert (ISDIGIT (*name));
197 name++;
198 gcc_assert (name == p);
202 return name;