pe.c revision 132718
1/* Routines for GCC for ARM/pe. 2 Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc. 3 Contributed by Doug Evans (dje@cygnus.com). 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 2, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 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 COPYING. If not, write to 19 the Free Software Foundation, 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "config.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "rtl.h" 27#include "output.h" 28#include "flags.h" 29#include "tree.h" 30#include "expr.h" 31#include "toplev.h" 32#include "tm_p.h" 33 34extern int current_function_anonymous_args; 35 36 37/* Return nonzero if DECL is a dllexport'd object. */ 38 39tree current_class_type; /* FIXME */ 40 41int 42arm_dllexport_p (decl) 43 tree decl; 44{ 45 tree exp; 46 47 if (TREE_CODE (decl) != VAR_DECL 48 && TREE_CODE (decl) != FUNCTION_DECL) 49 return 0; 50 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); 51 if (exp) 52 return 1; 53 54 return 0; 55} 56 57/* Return nonzero if DECL is a dllimport'd object. */ 58 59int 60arm_dllimport_p (decl) 61 tree decl; 62{ 63 tree imp; 64 65 if (TREE_CODE (decl) == FUNCTION_DECL 66 && TARGET_NOP_FUN_DLLIMPORT) 67 return 0; 68 69 if (TREE_CODE (decl) != VAR_DECL 70 && TREE_CODE (decl) != FUNCTION_DECL) 71 return 0; 72 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); 73 if (imp) 74 return 1; 75 76 return 0; 77} 78 79/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 80 81int 82arm_dllexport_name_p (symbol) 83 const char * symbol; 84{ 85 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.'; 86} 87 88/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 89 90int 91arm_dllimport_name_p (symbol) 92 const char * symbol; 93{ 94 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.'; 95} 96 97/* Mark a DECL as being dllexport'd. 98 Note that we override the previous setting (eg: dllimport). */ 99 100void 101arm_mark_dllexport (decl) 102 tree decl; 103{ 104 const char * oldname; 105 char * newname; 106 rtx rtlname; 107 tree idp; 108 109 rtlname = XEXP (DECL_RTL (decl), 0); 110 if (GET_CODE (rtlname) == SYMBOL_REF) 111 oldname = XSTR (rtlname, 0); 112 else if (GET_CODE (rtlname) == MEM 113 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 114 oldname = XSTR (XEXP (rtlname, 0), 0); 115 else 116 abort (); 117 if (arm_dllimport_name_p (oldname)) 118 oldname += 9; 119 else if (arm_dllexport_name_p (oldname)) 120 return; /* already done */ 121 122 newname = alloca (strlen (oldname) + 4); 123 sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname); 124 125 /* We pass newname through get_identifier to ensure it has a unique 126 address. RTL processing can sometimes peek inside the symbol ref 127 and compare the string's addresses to see if two symbols are 128 identical. */ 129 /* ??? At least I think that's why we do this. */ 130 idp = get_identifier (newname); 131 132 XEXP (DECL_RTL (decl), 0) = 133 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 134} 135 136/* Mark a DECL as being dllimport'd. */ 137 138void 139arm_mark_dllimport (decl) 140 tree decl; 141{ 142 const char * oldname; 143 char * newname; 144 tree idp; 145 rtx rtlname, newrtl; 146 147 rtlname = XEXP (DECL_RTL (decl), 0); 148 149 if (GET_CODE (rtlname) == SYMBOL_REF) 150 oldname = XSTR (rtlname, 0); 151 else if (GET_CODE (rtlname) == MEM 152 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 153 oldname = XSTR (XEXP (rtlname, 0), 0); 154 else 155 abort (); 156 157 if (arm_dllexport_name_p (oldname)) 158 abort (); /* this shouldn't happen */ 159 else if (arm_dllimport_name_p (oldname)) 160 return; /* already done */ 161 162 /* ??? One can well ask why we're making these checks here, 163 and that would be a good question. */ 164 165 /* Imported variables can't be initialized. */ 166 if (TREE_CODE (decl) == VAR_DECL 167 && !DECL_VIRTUAL_P (decl) 168 && DECL_INITIAL (decl)) 169 { 170 error ("%Jinitialized variable '%D' is marked dllimport", decl, decl); 171 return; 172 } 173 /* Nor can they be static. */ 174 if (TREE_CODE (decl) == VAR_DECL 175 /* ??? Is this test for vtables needed? */ 176 && !DECL_VIRTUAL_P (decl) 177 && 0 /*???*/) 178 { 179 error ("%Jstatic variable '%D' is marked dllimport", decl, decl); 180 return; 181 } 182 183 /* `extern' needn't be specified with dllimport. 184 Specify `extern' now and hope for the best. Sigh. */ 185 if (TREE_CODE (decl) == VAR_DECL 186 /* ??? Is this test for vtables needed? */ 187 && !DECL_VIRTUAL_P (decl)) 188 { 189 DECL_EXTERNAL (decl) = 1; 190 TREE_PUBLIC (decl) = 1; 191 } 192 193 newname = alloca (strlen (oldname) + 11); 194 sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname); 195 196 /* We pass newname through get_identifier to ensure it has a unique 197 address. RTL processing can sometimes peek inside the symbol ref 198 and compare the string's addresses to see if two symbols are 199 identical. */ 200 /* ??? At least I think that's why we do this. */ 201 idp = get_identifier (newname); 202 203 newrtl = gen_rtx (MEM, Pmode, 204 gen_rtx (SYMBOL_REF, Pmode, 205 IDENTIFIER_POINTER (idp))); 206 XEXP (DECL_RTL (decl), 0) = newrtl; 207} 208 209void 210arm_pe_encode_section_info (decl, rtl, first) 211 tree decl; 212 rtx rtl; 213 int first ATTRIBUTE_UNUSED; 214{ 215 /* This bit is copied from arm_encode_section_info. */ 216 if (optimize > 0 && TREE_CONSTANT (decl) 217 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) 218 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; 219 220 /* Mark the decl so we can tell from the rtl whether the object is 221 dllexport'd or dllimport'd. */ 222 if (arm_dllexport_p (decl)) 223 arm_mark_dllexport (decl); 224 else if (arm_dllimport_p (decl)) 225 arm_mark_dllimport (decl); 226 /* It might be that DECL has already been marked as dllimport, but a 227 subsequent definition nullified that. The attribute is gone but 228 DECL_RTL still has @i.__imp_foo. We need to remove that. */ 229 else if ((TREE_CODE (decl) == FUNCTION_DECL 230 || TREE_CODE (decl) == VAR_DECL) 231 && DECL_RTL (decl) != NULL_RTX 232 && GET_CODE (DECL_RTL (decl)) == MEM 233 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM 234 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF 235 && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) 236 { 237 const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); 238 tree idp = get_identifier (oldname + 9); 239 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 240 241 XEXP (DECL_RTL (decl), 0) = newrtl; 242 243 /* We previously set TREE_PUBLIC and DECL_EXTERNAL. 244 ??? We leave these alone for now. */ 245 } 246} 247 248void 249arm_pe_unique_section (decl, reloc) 250 tree decl; 251 int reloc; 252{ 253 int len; 254 const char * name; 255 char * string; 256 const char * prefix; 257 258 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 259 name = arm_strip_name_encoding (name); 260 261 /* The object is put in, for example, section .text$foo. 262 The linker will then ultimately place them in .text 263 (everything from the $ on is stripped). */ 264 if (TREE_CODE (decl) == FUNCTION_DECL) 265 prefix = ".text$"; 266 else if (decl_readonly_section (decl, reloc)) 267 prefix = ".rdata$"; 268 else 269 prefix = ".data$"; 270 len = strlen (name) + strlen (prefix); 271 string = alloca (len + 1); 272 sprintf (string, "%s%s", prefix, name); 273 274 DECL_SECTION_NAME (decl) = build_string (len, string); 275} 276