1169689Skan/* Subroutines for insn-output.c for NetWare. 2169689Skan Contributed by Jan Beulich (jbeulich@novell.com) 3169689Skan Copyright (C) 2004, 2005 Free Software Foundation, Inc. 4169689Skan 5169689SkanThis file is part of GCC. 6169689Skan 7169689SkanGCC is free software; you can redistribute it and/or modify 8169689Skanit under the terms of the GNU General Public License as published by 9169689Skanthe Free Software Foundation; either version 2, or (at your option) 10169689Skanany later version. 11169689Skan 12169689SkanGCC is distributed in the hope that it will be useful, 13169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 14169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15169689SkanGNU General Public License for more details. 16169689Skan 17169689SkanYou should have received a copy of the GNU General Public License 18169689Skanalong with GCC; see the file COPYING. If not, write to 19169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 20169689SkanBoston, MA 02110-1301, USA. */ 21169689Skan 22169689Skan#include "config.h" 23169689Skan#include "system.h" 24169689Skan#include "coretypes.h" 25169689Skan#include "tm.h" 26169689Skan#include "rtl.h" 27169689Skan#include "regs.h" 28169689Skan#include "hard-reg-set.h" 29169689Skan#include "output.h" 30169689Skan#include "tree.h" 31169689Skan#include "flags.h" 32169689Skan#include "tm_p.h" 33169689Skan#include "toplev.h" 34169689Skan#include "ggc.h" 35169689Skan 36169689Skan 37169689Skan/* Return string which is the former assembler name modified with an 38169689Skan underscore prefix and a suffix consisting of an atsign (@) followed 39169689Skan by the number of bytes of arguments */ 40169689Skan 41169689Skanstatic tree 42169689Skangen_stdcall_or_fastcall_decoration (tree decl, char prefix) 43169689Skan{ 44169689Skan unsigned total = 0; 45169689Skan /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 46169689Skan of DECL_ASSEMBLER_NAME. */ 47169689Skan const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 48169689Skan char *newsym; 49169689Skan tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 50169689Skan 51169689Skan if (formal_type != NULL_TREE) 52169689Skan { 53169689Skan /* These attributes are ignored for variadic functions in 54169689Skan i386.c:ix86_return_pops_args. For compatibility with MS 55169689Skan compiler do not add @0 suffix here. */ 56169689Skan if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 57169689Skan return NULL_TREE; 58169689Skan 59169689Skan /* Quit if we hit an incomplete type. Error is reported 60169689Skan by convert_arguments in c-typeck.c or cp/typeck.c. */ 61169689Skan while (TREE_VALUE (formal_type) != void_type_node 62169689Skan && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 63169689Skan { 64169689Skan unsigned parm_size 65169689Skan = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 66169689Skan 67169689Skan /* Must round up to include padding. This is done the same 68169689Skan way as in store_one_arg. */ 69169689Skan parm_size = ((parm_size + PARM_BOUNDARY - 1) 70169689Skan / PARM_BOUNDARY * PARM_BOUNDARY); 71169689Skan total += parm_size; 72169689Skan formal_type = TREE_CHAIN (formal_type); 73169689Skan } 74169689Skan } 75169689Skan 76169689Skan newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1); 77169689Skan return get_identifier_with_length (newsym, 78169689Skan sprintf (newsym, 79169689Skan "%c%s@%u", 80169689Skan prefix, 81169689Skan asmname, 82169689Skan total / BITS_PER_UNIT)); 83169689Skan} 84169689Skan 85169689Skan/* Return string which is the former assembler name modified with an 86169689Skan _n@ prefix where n represents the number of arguments passed in 87169689Skan registers */ 88169689Skan 89169689Skanstatic tree 90169689Skangen_regparm_prefix (tree decl, unsigned nregs) 91169689Skan{ 92169689Skan unsigned total = 0; 93169689Skan /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 94169689Skan of DECL_ASSEMBLER_NAME. */ 95169689Skan const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 96169689Skan char *newsym; 97169689Skan tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 98169689Skan 99169689Skan if (formal_type != NULL_TREE) 100169689Skan { 101169689Skan /* This attribute is ignored for variadic functions. */ 102169689Skan if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 103169689Skan return NULL_TREE; 104169689Skan 105169689Skan /* Quit if we hit an incomplete type. Error is reported 106169689Skan by convert_arguments in c-typeck.c or cp/typeck.c. */ 107169689Skan while (TREE_VALUE (formal_type) != void_type_node 108169689Skan && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 109169689Skan { 110169689Skan unsigned parm_size 111169689Skan = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 112169689Skan 113169689Skan /* Must round up to include padding. This is done the same 114169689Skan way as in store_one_arg. */ 115169689Skan parm_size = ((parm_size + PARM_BOUNDARY - 1) 116169689Skan / PARM_BOUNDARY * PARM_BOUNDARY); 117169689Skan total += parm_size; 118169689Skan formal_type = TREE_CHAIN (formal_type); 119169689Skan } 120169689Skan } 121169689Skan 122169689Skan if (nregs > total / BITS_PER_WORD) 123169689Skan nregs = total / BITS_PER_WORD; 124169689Skan gcc_assert (nregs <= 9); 125169689Skan newsym = alloca (3 + strlen (asmname) + 1); 126169689Skan return get_identifier_with_length (newsym, 127169689Skan sprintf (newsym, 128169689Skan "_%u@%s", 129169689Skan nregs, 130169689Skan asmname)); 131169689Skan} 132169689Skan 133169689Skanvoid 134169689Skani386_nlm_encode_section_info (tree decl, rtx rtl, int first) 135169689Skan{ 136169689Skan default_encode_section_info (decl, rtl, first); 137169689Skan 138169689Skan if (first 139169689Skan && TREE_CODE (decl) == FUNCTION_DECL 140169689Skan && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*' 141169689Skan && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@')) 142169689Skan { 143169689Skan tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 144169689Skan tree newid; 145169689Skan 146169689Skan if (lookup_attribute ("stdcall", type_attributes)) 147169689Skan newid = gen_stdcall_or_fastcall_decoration (decl, '_'); 148169689Skan else if (lookup_attribute ("fastcall", type_attributes)) 149169689Skan newid = gen_stdcall_or_fastcall_decoration (decl, FASTCALL_PREFIX); 150169689Skan else if ((newid = lookup_attribute ("regparm", type_attributes)) != NULL_TREE) 151169689Skan newid = gen_regparm_prefix (decl, 152169689Skan TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (newid)))); 153169689Skan if (newid != NULL_TREE) 154169689Skan { 155169689Skan rtx rtlname = XEXP (rtl, 0); 156169689Skan 157169689Skan if (GET_CODE (rtlname) == MEM) 158169689Skan rtlname = XEXP (rtlname, 0); 159169689Skan XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); 160169689Skan /* These attributes must be present on first declaration, 161169689Skan change_decl_assembler_name will warn if they are added 162169689Skan later and the decl has been referenced, but duplicate_decls 163169689Skan should catch the mismatch before this is called. */ 164169689Skan change_decl_assembler_name (decl, newid); 165169689Skan } 166169689Skan } 167169689Skan} 168169689Skan 169169689Skan/* Strip the stdcall/fastcall/regparm pre-/suffix. */ 170169689Skan 171169689Skanconst char * 172169689Skani386_nlm_strip_name_encoding (const char *str) 173169689Skan{ 174169689Skan const char *name = default_strip_name_encoding (str); 175169689Skan 176169689Skan if (*str != '*' && (*name == '_' || *name == '@')) 177169689Skan { 178169689Skan const char *p = strchr (name + 1, '@'); 179169689Skan 180169689Skan if (p) 181169689Skan { 182169689Skan ++name; 183169689Skan if (ISDIGIT (p[1])) 184169689Skan name = ggc_alloc_string (name, p - name); 185169689Skan else 186169689Skan { 187169689Skan gcc_assert (ISDIGIT (*name)); 188169689Skan name++; 189169689Skan gcc_assert (name == p); 190169689Skan } 191169689Skan } 192169689Skan } 193169689Skan return name; 194169689Skan} 195