1/* Subroutines for insn-output.c for NetWare. 2 Contributed by Jan Beulich (jbeulich@novell.com) 3 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to 19the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20Boston, MA 02110-1301, USA. */ 21 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" 35 36 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 */ 40 41static tree 42gen_stdcall_or_fastcall_decoration (tree decl, char prefix) 43{ 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; 49 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 50 51 if (formal_type != NULL_TREE) 52 { 53 /* These attributes are ignored for variadic functions in 54 i386.c:ix86_return_pops_args. For compatibility with MS 55 compiler do not add @0 suffix here. */ 56 if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 57 return NULL_TREE; 58 59 /* Quit if we hit an incomplete type. Error is reported 60 by convert_arguments in c-typeck.c or cp/typeck.c. */ 61 while (TREE_VALUE (formal_type) != void_type_node 62 && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 63 { 64 unsigned parm_size 65 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 66 67 /* Must round up to include padding. This is done the same 68 way as in store_one_arg. */ 69 parm_size = ((parm_size + PARM_BOUNDARY - 1) 70 / PARM_BOUNDARY * PARM_BOUNDARY); 71 total += parm_size; 72 formal_type = TREE_CHAIN (formal_type); 73 } 74 } 75 76 newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1); 77 return get_identifier_with_length (newsym, 78 sprintf (newsym, 79 "%c%s@%u", 80 prefix, 81 asmname, 82 total / BITS_PER_UNIT)); 83} 84 85/* Return string which is the former assembler name modified with an 86 _n@ prefix where n represents the number of arguments passed in 87 registers */ 88 89static tree 90gen_regparm_prefix (tree decl, unsigned nregs) 91{ 92 unsigned total = 0; 93 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 94 of DECL_ASSEMBLER_NAME. */ 95 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 96 char *newsym; 97 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 98 99 if (formal_type != NULL_TREE) 100 { 101 /* This attribute is ignored for variadic functions. */ 102 if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 103 return NULL_TREE; 104 105 /* Quit if we hit an incomplete type. Error is reported 106 by convert_arguments in c-typeck.c or cp/typeck.c. */ 107 while (TREE_VALUE (formal_type) != void_type_node 108 && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 109 { 110 unsigned parm_size 111 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 112 113 /* Must round up to include padding. This is done the same 114 way as in store_one_arg. */ 115 parm_size = ((parm_size + PARM_BOUNDARY - 1) 116 / PARM_BOUNDARY * PARM_BOUNDARY); 117 total += parm_size; 118 formal_type = TREE_CHAIN (formal_type); 119 } 120 } 121 122 if (nregs > total / BITS_PER_WORD) 123 nregs = total / BITS_PER_WORD; 124 gcc_assert (nregs <= 9); 125 newsym = alloca (3 + strlen (asmname) + 1); 126 return get_identifier_with_length (newsym, 127 sprintf (newsym, 128 "_%u@%s", 129 nregs, 130 asmname)); 131} 132 133void 134i386_nlm_encode_section_info (tree decl, rtx rtl, int first) 135{ 136 default_encode_section_info (decl, rtl, first); 137 138 if (first 139 && TREE_CODE (decl) == FUNCTION_DECL 140 && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*' 141 && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@')) 142 { 143 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 144 tree newid; 145 146 if (lookup_attribute ("stdcall", type_attributes)) 147 newid = gen_stdcall_or_fastcall_decoration (decl, '_'); 148 else if (lookup_attribute ("fastcall", type_attributes)) 149 newid = gen_stdcall_or_fastcall_decoration (decl, FASTCALL_PREFIX); 150 else if ((newid = lookup_attribute ("regparm", type_attributes)) != NULL_TREE) 151 newid = gen_regparm_prefix (decl, 152 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (newid)))); 153 if (newid != NULL_TREE) 154 { 155 rtx rtlname = XEXP (rtl, 0); 156 157 if (GET_CODE (rtlname) == MEM) 158 rtlname = XEXP (rtlname, 0); 159 XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); 160 /* These attributes must be present on first declaration, 161 change_decl_assembler_name will warn if they are added 162 later and the decl has been referenced, but duplicate_decls 163 should catch the mismatch before this is called. */ 164 change_decl_assembler_name (decl, newid); 165 } 166 } 167} 168 169/* Strip the stdcall/fastcall/regparm pre-/suffix. */ 170 171const char * 172i386_nlm_strip_name_encoding (const char *str) 173{ 174 const char *name = default_strip_name_encoding (str); 175 176 if (*str != '*' && (*name == '_' || *name == '@')) 177 { 178 const char *p = strchr (name + 1, '@'); 179 180 if (p) 181 { 182 ++name; 183 if (ISDIGIT (p[1])) 184 name = ggc_alloc_string (name, p - name); 185 else 186 { 187 gcc_assert (ISDIGIT (*name)); 188 name++; 189 gcc_assert (name == p); 190 } 191 } 192 } 193 return name; 194} 195