OSDN Git Service

Revert:
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / netware.c
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.
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
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 */
39
40 static tree
41 gen_stdcall_or_fastcall_decoration (tree decl, char prefix)
42 {
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 formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
49
50   if (formal_type != NULL_TREE)
51     {
52       /* These attributes are ignored for variadic functions in
53          i386.c:ix86_return_pops_args. For compatibility with MS
54          compiler do not add @0 suffix here.  */ 
55       if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
56         return NULL_TREE;
57
58       /* Quit if we hit an incomplete type.  Error is reported
59          by convert_arguments in c-typeck.c or cp/typeck.c.  */
60       while (TREE_VALUE (formal_type) != void_type_node
61              && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))     
62         {
63           unsigned parm_size
64             = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
65
66           /* Must round up to include padding.  This is done the same
67              way as in store_one_arg.  */
68           parm_size = ((parm_size + PARM_BOUNDARY - 1)
69                        / PARM_BOUNDARY * PARM_BOUNDARY);
70           total += parm_size;
71           formal_type = TREE_CHAIN (formal_type);
72         }
73     }
74
75   newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1);
76   return get_identifier_with_length (newsym,
77                                      sprintf (newsym,
78                                               "%c%s@%u",
79                                               prefix,
80                                               asmname,
81                                               total / BITS_PER_UNIT));
82 }
83
84 /* Return string which is the former assembler name modified with an 
85    _n@ prefix where n represents the number of arguments passed in
86    registers */
87
88 static tree
89 gen_regparm_prefix (tree decl, unsigned nregs)
90 {
91   unsigned total = 0;
92   /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
93      of DECL_ASSEMBLER_NAME.  */
94   const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
95   char *newsym;
96   tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
97
98   if (formal_type != NULL_TREE)
99     {
100       /* This attribute is ignored for variadic functions.  */ 
101       if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
102         return NULL_TREE;
103
104       /* Quit if we hit an incomplete type.  Error is reported
105          by convert_arguments in c-typeck.c or cp/typeck.c.  */
106       while (TREE_VALUE (formal_type) != void_type_node
107              && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))     
108         {
109           unsigned parm_size
110             = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
111
112           /* Must round up to include padding.  This is done the same
113              way as in store_one_arg.  */
114           parm_size = ((parm_size + PARM_BOUNDARY - 1)
115                        / PARM_BOUNDARY * PARM_BOUNDARY);
116           total += parm_size;
117           formal_type = TREE_CHAIN (formal_type);
118         }
119     }
120
121   if (nregs > total / BITS_PER_WORD)
122     nregs = total / BITS_PER_WORD;
123   gcc_assert (nregs <= 9);
124   newsym = alloca (3 + strlen (asmname) + 1);
125   return get_identifier_with_length (newsym,
126                                      sprintf (newsym,
127                                               "_%u@%s",
128                                               nregs,
129                                               asmname));
130 }
131
132 void
133 i386_nlm_encode_section_info (tree decl, rtx rtl, int first)
134 {
135   default_encode_section_info (decl, rtl, first);
136
137   if (first
138       && TREE_CODE (decl) == FUNCTION_DECL
139       && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*'
140       && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@'))
141     {
142       tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
143       tree newid;
144
145       if (lookup_attribute ("stdcall", type_attributes))
146         newid = gen_stdcall_or_fastcall_decoration (decl, '_');
147       else if (lookup_attribute ("fastcall", type_attributes))
148         newid = gen_stdcall_or_fastcall_decoration (decl, FASTCALL_PREFIX);
149       else if ((newid = lookup_attribute ("regparm", type_attributes)) != NULL_TREE)
150         newid = gen_regparm_prefix (decl,
151                       TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (newid))));
152       if (newid != NULL_TREE)   
153         {
154           rtx rtlname = XEXP (rtl, 0);
155
156           if (GET_CODE (rtlname) == MEM)
157             rtlname = XEXP (rtlname, 0);
158           XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
159           /* These attributes must be present on first declaration,
160              change_decl_assembler_name will warn if they are added
161              later and the decl has been referenced, but duplicate_decls
162              should catch the mismatch before this is called.  */ 
163           change_decl_assembler_name (decl, newid);
164         }
165     }
166 }
167
168 /* Strip the stdcall/fastcall/regparm pre-/suffix.  */
169
170 const char *
171 i386_nlm_strip_name_encoding (const char *str)
172 {
173   const char *name = default_strip_name_encoding (str);
174
175   if (*str != '*' && (*name == '_' || *name == '@'))
176     {
177       const char *p = strchr (name + 1, '@');
178
179       if (p)
180         {
181           ++name;
182           if (ISDIGIT (p[1]))
183             name = ggc_alloc_string (name, p - name);
184           else
185             {
186               gcc_assert (ISDIGIT (*name));
187               name++;
188               gcc_assert (name == p);
189             }
190         }
191     }
192   return name;
193 }