source: trunk/src/gcc/gcc/config/i386/emx.c@ 603

Last change on this file since 603 was 603, checked in by bird, 22 years ago

#570,#572: Did all the weird cases and fixed the strcmp. yeah, and removed all the gotos.

  • Property cvs2svn:cvs-rev set to 1.14
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1/* emx.c: Functions for emx as target system.
2
3Original version by Eberhard Mattes, based on i386.c.
4Heavily modified by Andrew Zabolotny and Knut St. Osmundsen.
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU CC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING. If not, write to
20the Free Software Foundation, 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA. */
22
23#include "config.h"
24#include "system.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 "toplev.h"
31#include "flags.h"
32
33
34/* The size of the target's pointer type. */
35#ifndef PTR_SIZE
36#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
37#endif
38
39/** @todo remove debug code */
40/*#define BIRD_DEBUG*/
41#ifdef BIRD_DEBUG
42static const char *code(tree node)
43{
44 if (node)
45 {
46 switch (TREE_CODE (node))
47 {
48 case FUNCTION_TYPE: return "FUNCTION_TYPE";
49 case FUNCTION_DECL: return "FUNCTION_DECL";
50 case METHOD_TYPE: return "METHOD_TYPE";
51 case FIELD_DECL: return "FIELD_DECL";
52 case TYPE_DECL: return "TYPE_DECL";
53 case POINTER_TYPE: return "POINTER_TYPE";
54 case VOID_TYPE: return "VOID_TYPE";
55 case INTEGER_TYPE: return "INTEGER_TYPE";
56 case CHAR_TYPE: return "CHAR_TYPE";
57 case SET_TYPE: return "SET_TYPE";
58 case ARRAY_TYPE: return "ARRAY_TYPE";
59 case RECORD_TYPE: return "RECORD_TYPE";
60 case QUAL_UNION_TYPE: return "QUAL_UNION_TYPE";
61 case UNION_TYPE: return "UNION_TYPE";
62 default:
63 break;
64 }
65 }
66 return "";
67}
68
69void dump (tree node);
70void dump (tree node)
71{
72 tree type, type2, context, name;
73 if (!node)
74 return;
75
76 type = TREE_TYPE (node);
77 type2 = type ? TREE_TYPE(type) : NULL;
78 context = DECL_P (node) ? DECL_CONTEXT (node) : NULL_TREE;
79 name = DECL_P (node) ? DECL_NAME (node) : NULL_TREE;
80 fprintf(stderr, "dbg: node=%d %s type=%d %s type_type=%d %s context=%d %s name=%s\n",
81 TREE_CODE(node), code(node),
82 type ? TREE_CODE(type) : -1, code(type),
83 type2 ? TREE_CODE(type2) : -1, code(type2),
84 context ? TREE_CODE(context) : -1, code(context),
85 name ? IDENTIFIER_POINTER (name) : "<none>");
86}
87
88#define dfprintf(a) fprintf a
89#define DUMP(node) dump(node)
90#else
91#define dfprintf(a) do {} while (0)
92#define DUMP(node) do {} while (0)
93#endif
94
95
96tree ix86_handle_vacpp_attribute (tree *node, tree name, tree args,
97 int flags, bool *no_add_attrs)
98{
99 tree id, type, context;
100 size_t sl;
101 const char *oldsym;
102 char *newsym;
103
104 DUMP (*node);
105
106 switch (TREE_CODE (*node))
107 {
108 case FUNCTION_DECL:
109 /* This is the core of attribute handling. Every other code is
110 designed so that we end up with a function declaration and
111 an attached attribute (either optlink or system).
112 This is the only part which is changing the mangling. */
113 if ( !strcmp (IDENTIFIER_POINTER (name), "__system__")
114 || !strcmp (IDENTIFIER_POINTER (name), "system") )
115 {
116 /* Here we mangle _System functions as defined by IBM specs.
117 The function always gets its name as-is (unless it is a method,
118 which is a undefined case as VACPP always use _Optlink for methods,
119 at least that's what I have understood from the docs). */
120 /* @todo: verify the class detection here! Does it require use of
121 CLASSTYPE_DECLARED_CLASS (meaning it doesn't applies to plain
122 structs/unions) ? */
123 if ( TREE_CODE (TREE_TYPE (*node)) != METHOD_TYPE
124 && ( !(context = DECL_CONTEXT (*node))
125 || ( TREE_CODE (context) != RECORD_TYPE
126 && TREE_CODE (context) != UNION_TYPE)))
127 {
128 oldsym = IDENTIFIER_POINTER (DECL_NAME (*node));
129 /* Specifying '*' as first symbol character tells gcc (see varasm.c,
130 function assemble_name()) to output the label as-is rather than
131 invoking the ASM_OUTPUT_LABELREF macro (which prepends a underscore) */
132 sl = strlen (oldsym);
133 newsym = xmalloc (sl + 2);
134 newsym [0] = '*';
135 memcpy (newsym + 1, oldsym, sl + 1);
136 SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
137 dfprintf((stderr, "dbg: system %s -> %s\n", oldsym, newsym));
138 }
139 }
140 else if ( !strcmp (IDENTIFIER_POINTER (name), "__optlink__")
141 || !strcmp (IDENTIFIER_POINTER (name), "optlink"))
142 {
143 /* At the moment we're only implementing OS/2 VAC linking
144 compatibility for the C language. This means that no leading
145 underscore.
146 For C++ we are not compatible. It doesn't make that much sense
147 either since we're not VFT compatible either. For simplisity
148 and safty we are removing the leading underscore from the
149 default mangled names to catch invalid declarations in the
150 linking. */
151
152 id = DECL_ASSEMBLER_NAME (*node);
153 /* Remove the leading underscore. */
154 oldsym = IDENTIFIER_POINTER (id);
155 sl = strlen (oldsym);
156 newsym = xmalloc (sl + 2);
157 newsym [0] = '*';
158 memcpy (newsym + 1, oldsym, sl + 1);
159 XEXP (DECL_RTL (*node), 0) = gen_rtx (SYMBOL_REF, Pmode,
160 IDENTIFIER_POINTER (get_identifier (newsym)));
161 dfprintf((stderr, "dbg: optlink %s -> %s\n", oldsym, newsym));
162 }
163 else /* Internal error!!! */
164 {
165 warning ("`%s' is an unknown attribute name for ix86_handle_vacpp_attribute()",
166 IDENTIFIER_POINTER (name));
167 *no_add_attrs = true;
168 break;
169 }
170
171 /* The attribute should really be attached to our _TYPE,
172 not to the _DECL. (yeah, we need to do this!) */
173 type = TREE_TYPE (*node);
174 TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
175 tree_cons (name, args, NULL_TREE));
176 *no_add_attrs = true;
177 break;
178
179 /* Only function declarations needs mangling changes, however other
180 declarations involving function types needs to get the parameter
181 passing right. */
182 case FIELD_DECL:
183 /* Struct, union or class member declaration. Same handling as
184 type declarations. */
185 case TYPE_DECL:
186 /* If this is a type declaration with our attribute, we allow it
187 only if it is a pointer-to-a-function type or a function type. */
188 type = TREE_TYPE (*node);
189 if (TREE_CODE (type) == POINTER_TYPE)
190 type = TREE_TYPE(type);
191 if ( TREE_CODE (type) == FUNCTION_TYPE
192 || TREE_CODE (type) == METHOD_TYPE)
193 {
194 /* Attach the attribute to the (FUNCTION|METHOD)_TYPE node */
195 TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
196 tree_cons (name, args, NULL_TREE));
197 *no_add_attrs = true;
198 break;
199 }
200 warning ("`%s' attribute only applies to functions and function types (typecode=%d)",
201 IDENTIFIER_POINTER (name), type ? (int)TREE_CODE (type) : -1);
202 *no_add_attrs = true;
203 break;
204
205
206 /* For types involving functions we need to convince decl_attributes
207 (and it callers) to supply a declaration in case the mangling needs
208 to be changed. */
209 case POINTER_TYPE:
210 /* We allow:
211 This being the return type of a function which is coming soon.
212 This being a function pointer which declaration is coming next.
213 Everything else is concidered inappropriate use of the attribute. */
214 if ( !(flags & ATTR_FLAG_FUNCTION_NEXT)
215 && ( !(flags & ATTR_FLAG_DECL_NEXT)
216 || !(type = TREE_TYPE (*node))
217 || ( TREE_CODE (type) != FUNCTION_TYPE
218 && TREE_CODE (type) != METHOD_TYPE)))
219 {
220 warning ("`%s' attribute only applies to functions and function types (typecode=%d)",
221 IDENTIFIER_POINTER (name), type ? (int)TREE_CODE (type) : -1);
222 *no_add_attrs = true;
223 break;
224 }
225 /* fall thru */
226 case FUNCTION_TYPE:
227 case METHOD_TYPE:
228 *no_add_attrs = true;
229 return tree_cons (name, args, NULL_TREE);
230
231 default:
232 warning ("`%s' attribute only applies to functions and function types (code=%d)",
233 IDENTIFIER_POINTER (name), TREE_CODE (*node));
234 *no_add_attrs = true;
235 break;
236 }
237
238 return NULL_TREE;
239}
240
241void
242emx_eh_frame_section ()
243{
244/*
245 tree label = get_file_function_name ('F');
246 The __ehInit undefined external here is to drag __ehInit/__ehInitDLL into
247 the linking so DLLs are initiated correctly. (#577)
248*/
249 data_section ();
250 ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
251 fprintf (asm_out_file,
252 "\t.stabs\t\"___eh_frame__\",24,0,0,Lframe1\n" /* N_SETD */
253 "\t.stabs\t\"___ehInit\",1,0,0,0\n"); /* N_UNDEF | N_EXT */
254}
255
256/* Add a __POST$xxx label before epilogue if -mepilogue specified */
257void emx_output_function_begin_epilogue (FILE *f)
258{
259 if (TARGET_EPILOGUE && TREE_PUBLIC (current_function_decl))
260 {
261 const char *func_label = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
262 char *lbl = alloca (strlen (func_label) + 8);
263 strcpy (lbl, "__POST$");
264 if (func_label[0] == '*')
265 func_label++;
266 strcat (lbl, func_label);
267 ASM_OUTPUT_LABEL (f, lbl);
268 }
269}
270
271/* Return string which is the former assembler name modified with a
272 suffix consisting of an atsign (@) followed by the number of bytes of
273 arguments */
274
275const char *
276gen_stdcall_suffix (tree decl)
277{
278 int total = 0;
279 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
280 of DECL_ASSEMBLER_NAME. */
281 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
282 char *newsym;
283
284 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
285 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
286 == void_type_node)
287 {
288 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
289
290 while (TREE_VALUE (formal_type) != void_type_node)
291 {
292 int parm_size
293 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
294 /* Must round up to include padding. This is done the same
295 way as in store_one_arg. */
296 parm_size = ((parm_size + PARM_BOUNDARY - 1)
297 / PARM_BOUNDARY * PARM_BOUNDARY);
298 total += parm_size;
299 formal_type = TREE_CHAIN (formal_type);
300 }
301 }
302
303 newsym = xmalloc (strlen (asmname) + 10);
304 sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
305 return IDENTIFIER_POINTER (get_identifier (newsym));
306}
307
308/* Cover function to implement ENCODE_SECTION_INFO.
309 Note that this could be implemented much better by doing the
310 stdcall mangling like optlink and system, but unfortunately */
311
312void
313emx_encode_section_info (tree decl)
314{
315 /* The default ENCODE_SECTION_INFO from i386.h */
316 if (flag_pic)
317 {
318 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
319 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
320
321 if (GET_CODE (rtl) == MEM)
322 {
323 if (TARGET_DEBUG_ADDR
324 && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
325 {
326 fprintf (stderr, "Encode %s, public = %d\n",
327 IDENTIFIER_POINTER (DECL_NAME (decl)),
328 TREE_PUBLIC (decl));
329 }
330
331 SYMBOL_REF_FLAG (XEXP (rtl, 0))
332 = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
333 || ! TREE_PUBLIC (decl));
334 }
335 }
336
337 /* If declaring a function, mangle it if it's stdcall */
338 if (TREE_CODE (decl) == FUNCTION_DECL)
339 {
340 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
341 XEXP (DECL_RTL (decl), 0) =
342 gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
343 }
344}
Note: See TracBrowser for help on using the repository browser.