| 1 | /* emx.c: Functions for emx as target system.
|
|---|
| 2 |
|
|---|
| 3 | Original version by Eberhard Mattes, based on i386.c.
|
|---|
| 4 | Heavily modified by Andrew Zabolotny and Knut St. Osmundsen.
|
|---|
| 5 |
|
|---|
| 6 | This file is part of GNU CC.
|
|---|
| 7 |
|
|---|
| 8 | GNU CC is free software; you can redistribute it and/or modify
|
|---|
| 9 | it under the terms of the GNU General Public License as published by
|
|---|
| 10 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 11 | any later version.
|
|---|
| 12 |
|
|---|
| 13 | GNU CC is distributed in the hope that it will be useful,
|
|---|
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 16 | GNU General Public License for more details.
|
|---|
| 17 |
|
|---|
| 18 | You should have received a copy of the GNU General Public License
|
|---|
| 19 | along with GNU CC; see the file COPYING. If not, write to
|
|---|
| 20 | the Free Software Foundation, 59 Temple Place - Suite 330,
|
|---|
| 21 | Boston, 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 | /* Prototypes */
|
|---|
| 34 | static const char *gen_stdcall_suffix (tree);
|
|---|
| 35 |
|
|---|
| 36 | /* The size of the target's pointer type. */
|
|---|
| 37 | #ifndef PTR_SIZE
|
|---|
| 38 | #define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
|
|---|
| 39 | #endif
|
|---|
| 40 |
|
|---|
| 41 | /** @todo remove debug code */
|
|---|
| 42 | #define BIRD_DEBUG
|
|---|
| 43 | #ifdef BIRD_DEBUG
|
|---|
| 44 | static const char *code(tree node)
|
|---|
| 45 | {
|
|---|
| 46 | if (node)
|
|---|
| 47 | {
|
|---|
| 48 | switch (TREE_CODE (node))
|
|---|
| 49 | {
|
|---|
| 50 | case FUNCTION_TYPE: return "FUNCTION_TYPE";
|
|---|
| 51 | case FUNCTION_DECL: return "FUNCTION_DECL";
|
|---|
| 52 | case METHOD_TYPE: return "METHOD_TYPE";
|
|---|
| 53 | case FIELD_DECL: return "FIELD_DECL";
|
|---|
| 54 | case TYPE_DECL: return "TYPE_DECL";
|
|---|
| 55 | case POINTER_TYPE: return "POINTER_TYPE";
|
|---|
| 56 | case VOID_TYPE: return "VOID_TYPE";
|
|---|
| 57 | case INTEGER_TYPE: return "INTEGER_TYPE";
|
|---|
| 58 | case CHAR_TYPE: return "CHAR_TYPE";
|
|---|
| 59 | case SET_TYPE: return "SET_TYPE";
|
|---|
| 60 | case ARRAY_TYPE: return "ARRAY_TYPE";
|
|---|
| 61 | case RECORD_TYPE: return "RECORD_TYPE";
|
|---|
| 62 | case QUAL_UNION_TYPE: return "QUAL_UNION_TYPE";
|
|---|
| 63 | case UNION_TYPE: return "UNION_TYPE";
|
|---|
| 64 | default:
|
|---|
| 65 | break;
|
|---|
| 66 | }
|
|---|
| 67 | }
|
|---|
| 68 | return "";
|
|---|
| 69 | }
|
|---|
| 70 |
|
|---|
| 71 | static void dump (tree node);
|
|---|
| 72 | static void dump (tree node)
|
|---|
| 73 | {
|
|---|
| 74 | tree type, type2, context, name;
|
|---|
| 75 | if (!node)
|
|---|
| 76 | return;
|
|---|
| 77 |
|
|---|
| 78 | type = TREE_TYPE (node);
|
|---|
| 79 | type2 = type ? TREE_TYPE(type) : NULL;
|
|---|
| 80 | context = DECL_P (node) ? DECL_CONTEXT (node) : NULL_TREE;
|
|---|
| 81 | name = DECL_P (node) ? DECL_NAME (node) : NULL_TREE;
|
|---|
| 82 | fprintf(stderr, "dbg: node=%d %s type=%d %s type_type=%d %s context=%d %s name=%s\n",
|
|---|
| 83 | TREE_CODE(node), code(node),
|
|---|
| 84 | type ? (int)TREE_CODE(type) : -1, code(type),
|
|---|
| 85 | type2 ? (int)TREE_CODE(type2) : -1, code(type2),
|
|---|
| 86 | context ? (int)TREE_CODE(context) : -1, code(context),
|
|---|
| 87 | name ? IDENTIFIER_POINTER (name) : "<none>");
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | #define dfprintf(a) fprintf a
|
|---|
| 91 | #define DUMP(node) dump(node)
|
|---|
| 92 | #else
|
|---|
| 93 | #define dfprintf(a) do {} while (0)
|
|---|
| 94 | #define DUMP(node) do {} while (0)
|
|---|
| 95 | #endif
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 | tree ix86_handle_vacpp_attribute (tree *node, tree name, tree args,
|
|---|
| 99 | int flags, bool *no_add_attrs)
|
|---|
| 100 | {
|
|---|
| 101 | tree id, type, context;
|
|---|
| 102 | size_t sl;
|
|---|
| 103 | const char *oldsym;
|
|---|
| 104 | char *newsym;
|
|---|
| 105 |
|
|---|
| 106 | DUMP (*node);
|
|---|
| 107 |
|
|---|
| 108 | switch (TREE_CODE (*node))
|
|---|
| 109 | {
|
|---|
| 110 | case FUNCTION_DECL:
|
|---|
| 111 | /* This is the core of attribute handling. Every other code is
|
|---|
| 112 | designed so that we end up with a function declaration and
|
|---|
| 113 | an attached attribute (either optlink or system).
|
|---|
| 114 | This is the only part which is changing the mangling. */
|
|---|
| 115 | if (is_attribute_p ("system", name))
|
|---|
| 116 | {
|
|---|
| 117 | /* Here we mangle _System functions as defined by IBM specs.
|
|---|
| 118 | The function always gets its name as-is (unless it is a method,
|
|---|
| 119 | which is a undefined case as VACPP always use _Optlink for methods,
|
|---|
| 120 | at least that's what I have understood from the docs). */
|
|---|
| 121 | /* @todo: verify the class detection here! Does it require use of
|
|---|
| 122 | CLASSTYPE_DECLARED_CLASS (meaning it doesn't apply to plain
|
|---|
| 123 | structs/unions) ? */
|
|---|
| 124 | if ( TREE_CODE (TREE_TYPE (*node)) != METHOD_TYPE
|
|---|
| 125 | && ( !(context = DECL_CONTEXT (*node))
|
|---|
| 126 | || ( TREE_CODE (context) != RECORD_TYPE
|
|---|
| 127 | && TREE_CODE (context) != UNION_TYPE)))
|
|---|
| 128 | {
|
|---|
| 129 | oldsym = IDENTIFIER_POINTER (DECL_NAME (*node));
|
|---|
| 130 | /* Specifying '*' as first symbol character tells gcc (see varasm.c,
|
|---|
| 131 | function assemble_name()) to output the label as-is rather than
|
|---|
| 132 | invoking the ASM_OUTPUT_LABELREF macro (which prepends a underscore) */
|
|---|
| 133 | sl = strlen (oldsym);
|
|---|
| 134 | newsym = xmalloc (sl + 2);
|
|---|
| 135 | newsym [0] = '*';
|
|---|
| 136 | memcpy (newsym + 1, oldsym, sl + 1);
|
|---|
| 137 | SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
|
|---|
| 138 | dfprintf((stderr, "dbg: system %s -> %s\n", oldsym, newsym));
|
|---|
| 139 | }
|
|---|
| 140 | }
|
|---|
| 141 | else if (is_attribute_p ("optlink", name))
|
|---|
| 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 simplicity
|
|---|
| 148 | and safety 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 ("unexpected attribute `%s' in 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 | rather than to the _DECL. */
|
|---|
| 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 its 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 considered 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",
|
|---|
| 221 | IDENTIFIER_POINTER (name));
|
|---|
| 222 | *no_add_attrs = true;
|
|---|
| 223 | break;
|
|---|
| 224 | }
|
|---|
| 225 | /* fall thru */
|
|---|
| 226 | case FUNCTION_TYPE:
|
|---|
| 227 | case METHOD_TYPE:
|
|---|
| 228 | /* This branch is taken when a function/method type is encountered.
|
|---|
| 229 | We defer attribute handling until we get the complete declaration */
|
|---|
| 230 | *no_add_attrs = true;
|
|---|
| 231 | return tree_cons (name, args, NULL_TREE);
|
|---|
| 232 |
|
|---|
| 233 | default:
|
|---|
| 234 | warning ("`%s' attribute only applies to functions and function types (code=%d)",
|
|---|
| 235 | IDENTIFIER_POINTER (name), TREE_CODE (*node));
|
|---|
| 236 | *no_add_attrs = true;
|
|---|
| 237 | break;
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | return NULL_TREE;
|
|---|
| 241 | }
|
|---|
|
|---|