PR target/16201
[official-gcc.git] / gcc / config / i386 / netware.c
blob48985c1718362d217774b8f48489968f1d7dda9c
1 /* Subroutines for insn-output.c for NetWare.
2 Contributed by Jan Beulich (jbeulich@novell.com)
3 Copyright (C) 2004 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 2, 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 COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "output.h"
30 #include "tree.h"
31 #include "flags.h"
32 #include "tm_p.h"
33 #include "toplev.h"
34 #include "ggc.h"
37 /* Return string which is the former assembler name modified with an
38 underscore prefix and a suffix consisting of an atsign (@) followed
39 by the number of bytes of arguments */
41 static const char *
42 gen_stdcall_decoration (tree decl)
44 unsigned total = 0;
45 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
46 of DECL_ASSEMBLER_NAME. */
47 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
48 char *newsym;
50 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
51 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
52 == void_type_node)
54 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
56 /* Quit if we hit an incomplete type. Error is reported
57 by convert_arguments in c-typeck.c or cp/typeck.c. */
58 while (TREE_VALUE (formal_type) != void_type_node
59 && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
61 unsigned parm_size
62 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
63 /* Must round up to include padding. This is done the same
64 way as in store_one_arg. */
65 parm_size = ((parm_size + PARM_BOUNDARY - 1)
66 / PARM_BOUNDARY * PARM_BOUNDARY);
67 total += parm_size;
68 formal_type = TREE_CHAIN (formal_type);
72 newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1);
73 return IDENTIFIER_POINTER (get_identifier_with_length (newsym,
74 sprintf (newsym, "_%s@%u", asmname, total / BITS_PER_UNIT)));
77 /* Return string which is the former assembler name modified with a
78 prefix consisting of FASTCALL_PREFIX and a suffix consisting of an
79 atsign (@) followed by the number of bytes of arguments. */
81 static const char *
82 gen_fastcall_decoration (tree decl)
84 unsigned total = 0;
85 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
86 char *newsym;
88 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
89 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
90 == void_type_node)
92 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
94 /* Quit if we hit an incomplete type. Error is reported
95 by convert_arguments in c-typeck.c or cp/typeck.c. */
96 while (TREE_VALUE (formal_type) != void_type_node
97 && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
99 int parm_size
100 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
101 /* Must round up to include padding. This is done the same
102 way as in store_one_arg. */
103 parm_size = ((parm_size + PARM_BOUNDARY - 1)
104 / PARM_BOUNDARY * PARM_BOUNDARY);
105 total += parm_size;
106 formal_type = TREE_CHAIN (formal_type);
110 newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1);
111 return IDENTIFIER_POINTER (get_identifier_with_length (newsym,
112 sprintf (newsym, "%c%s@%d", FASTCALL_PREFIX, asmname,
113 total / BITS_PER_UNIT)));
116 /* Return string which is the former assembler name modified with an
117 _n@ prefix where n represents the number of arguments passed in
118 registers */
120 static const char *
121 gen_regparm_prefix (tree decl, unsigned nregs)
123 unsigned total = 0;
124 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
125 of DECL_ASSEMBLER_NAME. */
126 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
127 char *newsym;
129 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
130 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
131 == void_type_node)
133 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
135 /* Quit if we hit an incomplete type. Error is reported
136 by convert_arguments in c-typeck.c or cp/typeck.c. */
137 while (TREE_VALUE (formal_type) != void_type_node
138 && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
140 unsigned parm_size
141 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
142 /* Must round up to include padding. This is done the same
143 way as in store_one_arg. */
144 parm_size = ((parm_size + PARM_BOUNDARY - 1)
145 / PARM_BOUNDARY * PARM_BOUNDARY);
146 total += parm_size;
147 formal_type = TREE_CHAIN (formal_type);
151 if (nregs > total / BITS_PER_WORD)
152 nregs = total / BITS_PER_WORD;
153 if (nregs > 9) abort();
154 newsym = alloca (2 + strlen (asmname) + 1 + 1);
155 return IDENTIFIER_POINTER (get_identifier_with_length (newsym,
156 sprintf (newsym, "_%u@%s", nregs, asmname)));
159 void
160 i386_nlm_encode_section_info (tree decl, rtx rtl, int first)
162 default_encode_section_info (decl, rtl, first);
164 if (first
165 && TREE_CODE (decl) == FUNCTION_DECL
166 && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*')
168 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
169 rtx rtlname = XEXP (rtl, 0);
170 if (GET_CODE (rtlname) == MEM)
171 rtlname = XEXP (rtlname, 0);
172 if (lookup_attribute ("stdcall", type_attributes))
173 XSTR (rtlname, 0) = gen_stdcall_decoration (decl);
174 else if (lookup_attribute ("fastcall", type_attributes))
175 XSTR (rtlname, 0) = gen_fastcall_decoration (decl);
176 else
178 tree attr = lookup_attribute ("regparm", type_attributes);
180 if (attr)
181 XSTR (rtlname, 0) =
182 gen_regparm_prefix (decl,
183 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
188 /* Strip the stdcall/fastcall/regparm pre-/suffix. */
190 const char *
191 i386_nlm_strip_name_encoding (const char *str)
193 const char *name = default_strip_name_encoding (str);
195 if (*str != '*' && (*name == '_' || *name == '@'))
197 const char *p = strchr (name + 1, '@');
199 if (p)
201 ++name;
202 if (ISDIGIT (p[1]))
203 name = ggc_alloc_string (name, p - name);
204 else if (!ISDIGIT (*name) || ++name != p)
205 abort();
208 return name;