pe.c revision 132718
190075Sobrien/* Routines for GCC for ARM/pe. 2117395Skan Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc. 390075Sobrien Contributed by Doug Evans (dje@cygnus.com). 490075Sobrien 5132718Skan This file is part of GCC. 690075Sobrien 7132718Skan GCC is free software; you can redistribute it and/or modify it 8132718Skan under the terms of the GNU General Public License as published 9132718Skan by the Free Software Foundation; either version 2, or (at your 10132718Skan option) any later version. 1190075Sobrien 12132718Skan GCC is distributed in the hope that it will be useful, but WITHOUT 13132718Skan ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14132718Skan or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15132718Skan License for more details. 1690075Sobrien 17132718Skan You should have received a copy of the GNU General Public License 18132718Skan along with GCC; see the file COPYING. If not, write to 19132718Skan the Free Software Foundation, 59 Temple Place - Suite 330, 20132718Skan Boston, MA 02111-1307, USA. */ 2190075Sobrien 2290075Sobrien#include "config.h" 2390075Sobrien#include "system.h" 24132718Skan#include "coretypes.h" 25132718Skan#include "tm.h" 2690075Sobrien#include "rtl.h" 2790075Sobrien#include "output.h" 2890075Sobrien#include "flags.h" 2990075Sobrien#include "tree.h" 3090075Sobrien#include "expr.h" 3190075Sobrien#include "toplev.h" 3290075Sobrien#include "tm_p.h" 3390075Sobrien 3490075Sobrienextern int current_function_anonymous_args; 3590075Sobrien 3690075Sobrien 37117395Skan/* Return nonzero if DECL is a dllexport'd object. */ 3890075Sobrien 3990075Sobrientree current_class_type; /* FIXME */ 4090075Sobrien 4190075Sobrienint 4290075Sobrienarm_dllexport_p (decl) 4390075Sobrien tree decl; 4490075Sobrien{ 4590075Sobrien tree exp; 4690075Sobrien 4790075Sobrien if (TREE_CODE (decl) != VAR_DECL 4890075Sobrien && TREE_CODE (decl) != FUNCTION_DECL) 4990075Sobrien return 0; 5090075Sobrien exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); 5190075Sobrien if (exp) 5290075Sobrien return 1; 5390075Sobrien 5490075Sobrien return 0; 5590075Sobrien} 5690075Sobrien 57117395Skan/* Return nonzero if DECL is a dllimport'd object. */ 5890075Sobrien 5990075Sobrienint 6090075Sobrienarm_dllimport_p (decl) 6190075Sobrien tree decl; 6290075Sobrien{ 6390075Sobrien tree imp; 6490075Sobrien 6590075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 6690075Sobrien && TARGET_NOP_FUN_DLLIMPORT) 6790075Sobrien return 0; 6890075Sobrien 6990075Sobrien if (TREE_CODE (decl) != VAR_DECL 7090075Sobrien && TREE_CODE (decl) != FUNCTION_DECL) 7190075Sobrien return 0; 7290075Sobrien imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); 7390075Sobrien if (imp) 7490075Sobrien return 1; 7590075Sobrien 7690075Sobrien return 0; 7790075Sobrien} 7890075Sobrien 79117395Skan/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 8090075Sobrien 8190075Sobrienint 8290075Sobrienarm_dllexport_name_p (symbol) 8390075Sobrien const char * symbol; 8490075Sobrien{ 8590075Sobrien return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.'; 8690075Sobrien} 8790075Sobrien 88117395Skan/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 8990075Sobrien 9090075Sobrienint 9190075Sobrienarm_dllimport_name_p (symbol) 9290075Sobrien const char * symbol; 9390075Sobrien{ 9490075Sobrien return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.'; 9590075Sobrien} 9690075Sobrien 9790075Sobrien/* Mark a DECL as being dllexport'd. 9890075Sobrien Note that we override the previous setting (eg: dllimport). */ 9990075Sobrien 10090075Sobrienvoid 10190075Sobrienarm_mark_dllexport (decl) 10290075Sobrien tree decl; 10390075Sobrien{ 10490075Sobrien const char * oldname; 10590075Sobrien char * newname; 10690075Sobrien rtx rtlname; 10790075Sobrien tree idp; 10890075Sobrien 10990075Sobrien rtlname = XEXP (DECL_RTL (decl), 0); 11090075Sobrien if (GET_CODE (rtlname) == SYMBOL_REF) 11190075Sobrien oldname = XSTR (rtlname, 0); 11290075Sobrien else if (GET_CODE (rtlname) == MEM 11390075Sobrien && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 11490075Sobrien oldname = XSTR (XEXP (rtlname, 0), 0); 11590075Sobrien else 11690075Sobrien abort (); 11790075Sobrien if (arm_dllimport_name_p (oldname)) 11890075Sobrien oldname += 9; 11990075Sobrien else if (arm_dllexport_name_p (oldname)) 12090075Sobrien return; /* already done */ 12190075Sobrien 12290075Sobrien newname = alloca (strlen (oldname) + 4); 12390075Sobrien sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname); 12490075Sobrien 12590075Sobrien /* We pass newname through get_identifier to ensure it has a unique 12690075Sobrien address. RTL processing can sometimes peek inside the symbol ref 12790075Sobrien and compare the string's addresses to see if two symbols are 12890075Sobrien identical. */ 12990075Sobrien /* ??? At least I think that's why we do this. */ 13090075Sobrien idp = get_identifier (newname); 13190075Sobrien 13290075Sobrien XEXP (DECL_RTL (decl), 0) = 13390075Sobrien gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 13490075Sobrien} 13590075Sobrien 13690075Sobrien/* Mark a DECL as being dllimport'd. */ 13790075Sobrien 13890075Sobrienvoid 13990075Sobrienarm_mark_dllimport (decl) 14090075Sobrien tree decl; 14190075Sobrien{ 14290075Sobrien const char * oldname; 14390075Sobrien char * newname; 14490075Sobrien tree idp; 14590075Sobrien rtx rtlname, newrtl; 14690075Sobrien 14790075Sobrien rtlname = XEXP (DECL_RTL (decl), 0); 14890075Sobrien 14990075Sobrien if (GET_CODE (rtlname) == SYMBOL_REF) 15090075Sobrien oldname = XSTR (rtlname, 0); 15190075Sobrien else if (GET_CODE (rtlname) == MEM 15290075Sobrien && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 15390075Sobrien oldname = XSTR (XEXP (rtlname, 0), 0); 15490075Sobrien else 15590075Sobrien abort (); 15690075Sobrien 15790075Sobrien if (arm_dllexport_name_p (oldname)) 15890075Sobrien abort (); /* this shouldn't happen */ 15990075Sobrien else if (arm_dllimport_name_p (oldname)) 16090075Sobrien return; /* already done */ 16190075Sobrien 16290075Sobrien /* ??? One can well ask why we're making these checks here, 16390075Sobrien and that would be a good question. */ 16490075Sobrien 16590075Sobrien /* Imported variables can't be initialized. */ 16690075Sobrien if (TREE_CODE (decl) == VAR_DECL 16790075Sobrien && !DECL_VIRTUAL_P (decl) 16890075Sobrien && DECL_INITIAL (decl)) 16990075Sobrien { 170132718Skan error ("%Jinitialized variable '%D' is marked dllimport", decl, decl); 17190075Sobrien return; 17290075Sobrien } 17390075Sobrien /* Nor can they be static. */ 17490075Sobrien if (TREE_CODE (decl) == VAR_DECL 17590075Sobrien /* ??? Is this test for vtables needed? */ 17690075Sobrien && !DECL_VIRTUAL_P (decl) 17790075Sobrien && 0 /*???*/) 17890075Sobrien { 179132718Skan error ("%Jstatic variable '%D' is marked dllimport", decl, decl); 18090075Sobrien return; 18190075Sobrien } 18290075Sobrien 18390075Sobrien /* `extern' needn't be specified with dllimport. 18490075Sobrien Specify `extern' now and hope for the best. Sigh. */ 18590075Sobrien if (TREE_CODE (decl) == VAR_DECL 18690075Sobrien /* ??? Is this test for vtables needed? */ 18790075Sobrien && !DECL_VIRTUAL_P (decl)) 18890075Sobrien { 18990075Sobrien DECL_EXTERNAL (decl) = 1; 19090075Sobrien TREE_PUBLIC (decl) = 1; 19190075Sobrien } 19290075Sobrien 19390075Sobrien newname = alloca (strlen (oldname) + 11); 19490075Sobrien sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname); 19590075Sobrien 19690075Sobrien /* We pass newname through get_identifier to ensure it has a unique 19790075Sobrien address. RTL processing can sometimes peek inside the symbol ref 19890075Sobrien and compare the string's addresses to see if two symbols are 19990075Sobrien identical. */ 20090075Sobrien /* ??? At least I think that's why we do this. */ 20190075Sobrien idp = get_identifier (newname); 20290075Sobrien 20390075Sobrien newrtl = gen_rtx (MEM, Pmode, 20490075Sobrien gen_rtx (SYMBOL_REF, Pmode, 20590075Sobrien IDENTIFIER_POINTER (idp))); 20690075Sobrien XEXP (DECL_RTL (decl), 0) = newrtl; 20790075Sobrien} 20890075Sobrien 20990075Sobrienvoid 210132718Skanarm_pe_encode_section_info (decl, rtl, first) 21190075Sobrien tree decl; 212132718Skan rtx rtl; 213117395Skan int first ATTRIBUTE_UNUSED; 21490075Sobrien{ 215117395Skan /* This bit is copied from arm_encode_section_info. */ 21690075Sobrien if (optimize > 0 && TREE_CONSTANT (decl) 21790075Sobrien && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) 218132718Skan SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; 21990075Sobrien 22090075Sobrien /* Mark the decl so we can tell from the rtl whether the object is 22190075Sobrien dllexport'd or dllimport'd. */ 22290075Sobrien if (arm_dllexport_p (decl)) 22390075Sobrien arm_mark_dllexport (decl); 22490075Sobrien else if (arm_dllimport_p (decl)) 22590075Sobrien arm_mark_dllimport (decl); 22690075Sobrien /* It might be that DECL has already been marked as dllimport, but a 22790075Sobrien subsequent definition nullified that. The attribute is gone but 22890075Sobrien DECL_RTL still has @i.__imp_foo. We need to remove that. */ 22990075Sobrien else if ((TREE_CODE (decl) == FUNCTION_DECL 23090075Sobrien || TREE_CODE (decl) == VAR_DECL) 23190075Sobrien && DECL_RTL (decl) != NULL_RTX 23290075Sobrien && GET_CODE (DECL_RTL (decl)) == MEM 23390075Sobrien && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM 23490075Sobrien && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF 23590075Sobrien && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) 23690075Sobrien { 23790075Sobrien const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); 23890075Sobrien tree idp = get_identifier (oldname + 9); 23990075Sobrien rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 24090075Sobrien 24190075Sobrien XEXP (DECL_RTL (decl), 0) = newrtl; 24290075Sobrien 24390075Sobrien /* We previously set TREE_PUBLIC and DECL_EXTERNAL. 24490075Sobrien ??? We leave these alone for now. */ 24590075Sobrien } 24690075Sobrien} 24790075Sobrien 24890075Sobrienvoid 24990075Sobrienarm_pe_unique_section (decl, reloc) 25090075Sobrien tree decl; 25190075Sobrien int reloc; 25290075Sobrien{ 25390075Sobrien int len; 25490075Sobrien const char * name; 25590075Sobrien char * string; 25690075Sobrien const char * prefix; 25790075Sobrien 25890075Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 259117395Skan name = arm_strip_name_encoding (name); 26090075Sobrien 26190075Sobrien /* The object is put in, for example, section .text$foo. 26290075Sobrien The linker will then ultimately place them in .text 26390075Sobrien (everything from the $ on is stripped). */ 26490075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 26590075Sobrien prefix = ".text$"; 266117395Skan else if (decl_readonly_section (decl, reloc)) 26790075Sobrien prefix = ".rdata$"; 26890075Sobrien else 26990075Sobrien prefix = ".data$"; 27090075Sobrien len = strlen (name) + strlen (prefix); 27190075Sobrien string = alloca (len + 1); 27290075Sobrien sprintf (string, "%s%s", prefix, name); 27390075Sobrien 27490075Sobrien DECL_SECTION_NAME (decl) = build_string (len, string); 27590075Sobrien} 276