190075Sobrien/* Routines for GCC for ARM/pe. 2169689Skan Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004, 2005 3169689Skan Free Software Foundation, Inc. 490075Sobrien Contributed by Doug Evans (dje@cygnus.com). 590075Sobrien 6132718Skan This file is part of GCC. 790075Sobrien 8132718Skan GCC is free software; you can redistribute it and/or modify it 9132718Skan under the terms of the GNU General Public License as published 10132718Skan by the Free Software Foundation; either version 2, or (at your 11132718Skan option) any later version. 1290075Sobrien 13132718Skan GCC is distributed in the hope that it will be useful, but WITHOUT 14132718Skan ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15132718Skan or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16132718Skan License for more details. 1790075Sobrien 18132718Skan You should have received a copy of the GNU General Public License 19132718Skan along with GCC; see the file COPYING. If not, write to 20169689Skan the Free Software Foundation, 51 Franklin Street, Fifth Floor, 21169689Skan Boston, MA 02110-1301, USA. */ 2290075Sobrien 2390075Sobrien#include "config.h" 2490075Sobrien#include "system.h" 25132718Skan#include "coretypes.h" 26132718Skan#include "tm.h" 2790075Sobrien#include "rtl.h" 2890075Sobrien#include "output.h" 2990075Sobrien#include "flags.h" 3090075Sobrien#include "tree.h" 3190075Sobrien#include "expr.h" 3290075Sobrien#include "toplev.h" 3390075Sobrien#include "tm_p.h" 3490075Sobrien 3590075Sobrienextern int current_function_anonymous_args; 3690075Sobrien 3790075Sobrien 38117395Skan/* Return nonzero if DECL is a dllexport'd object. */ 3990075Sobrien 4090075Sobrientree current_class_type; /* FIXME */ 4190075Sobrien 4290075Sobrienint 4390075Sobrienarm_dllexport_p (decl) 4490075Sobrien tree decl; 4590075Sobrien{ 4690075Sobrien tree exp; 4790075Sobrien 4890075Sobrien if (TREE_CODE (decl) != VAR_DECL 4990075Sobrien && TREE_CODE (decl) != FUNCTION_DECL) 5090075Sobrien return 0; 5190075Sobrien exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); 5290075Sobrien if (exp) 5390075Sobrien return 1; 5490075Sobrien 5590075Sobrien return 0; 5690075Sobrien} 5790075Sobrien 58117395Skan/* Return nonzero if DECL is a dllimport'd object. */ 5990075Sobrien 6090075Sobrienint 6190075Sobrienarm_dllimport_p (decl) 6290075Sobrien tree decl; 6390075Sobrien{ 6490075Sobrien tree imp; 6590075Sobrien 6690075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 6790075Sobrien && TARGET_NOP_FUN_DLLIMPORT) 6890075Sobrien return 0; 6990075Sobrien 7090075Sobrien if (TREE_CODE (decl) != VAR_DECL 7190075Sobrien && TREE_CODE (decl) != FUNCTION_DECL) 7290075Sobrien return 0; 7390075Sobrien imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); 7490075Sobrien if (imp) 7590075Sobrien return 1; 7690075Sobrien 7790075Sobrien return 0; 7890075Sobrien} 7990075Sobrien 80117395Skan/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 8190075Sobrien 8290075Sobrienint 8390075Sobrienarm_dllexport_name_p (symbol) 8490075Sobrien const char * symbol; 8590075Sobrien{ 8690075Sobrien return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.'; 8790075Sobrien} 8890075Sobrien 89117395Skan/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 9090075Sobrien 9190075Sobrienint 9290075Sobrienarm_dllimport_name_p (symbol) 9390075Sobrien const char * symbol; 9490075Sobrien{ 9590075Sobrien return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.'; 9690075Sobrien} 9790075Sobrien 9890075Sobrien/* Mark a DECL as being dllexport'd. 99169689Skan Note that we override the previous setting (e.g.: dllimport). */ 10090075Sobrien 10190075Sobrienvoid 10290075Sobrienarm_mark_dllexport (decl) 10390075Sobrien tree decl; 10490075Sobrien{ 10590075Sobrien const char * oldname; 10690075Sobrien char * newname; 10790075Sobrien rtx rtlname; 10890075Sobrien tree idp; 10990075Sobrien 11090075Sobrien rtlname = XEXP (DECL_RTL (decl), 0); 111169689Skan if (GET_CODE (rtlname) == MEM) 112169689Skan rtlname = XEXP (rtlname, 0); 113169689Skan gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 114169689Skan oldname = XSTR (rtlname, 0); 115169689Skan 11690075Sobrien if (arm_dllimport_name_p (oldname)) 11790075Sobrien oldname += 9; 11890075Sobrien else if (arm_dllexport_name_p (oldname)) 11990075Sobrien return; /* already done */ 12090075Sobrien 12190075Sobrien newname = alloca (strlen (oldname) + 4); 12290075Sobrien sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname); 12390075Sobrien 12490075Sobrien /* We pass newname through get_identifier to ensure it has a unique 12590075Sobrien address. RTL processing can sometimes peek inside the symbol ref 12690075Sobrien and compare the string's addresses to see if two symbols are 12790075Sobrien identical. */ 12890075Sobrien /* ??? At least I think that's why we do this. */ 12990075Sobrien idp = get_identifier (newname); 13090075Sobrien 13190075Sobrien XEXP (DECL_RTL (decl), 0) = 132169689Skan gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 13390075Sobrien} 13490075Sobrien 13590075Sobrien/* Mark a DECL as being dllimport'd. */ 13690075Sobrien 13790075Sobrienvoid 13890075Sobrienarm_mark_dllimport (decl) 13990075Sobrien tree decl; 14090075Sobrien{ 14190075Sobrien const char * oldname; 14290075Sobrien char * newname; 14390075Sobrien tree idp; 14490075Sobrien rtx rtlname, newrtl; 14590075Sobrien 14690075Sobrien rtlname = XEXP (DECL_RTL (decl), 0); 14790075Sobrien 148169689Skan if (GET_CODE (rtlname) == MEM) 149169689Skan rtlname = XEXP (rtlname, 0); 150169689Skan gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 151169689Skan oldname = XSTR (rtlname, 0); 15290075Sobrien 153169689Skan gcc_assert (!arm_dllexport_name_p (oldname)); 154169689Skan if (arm_dllimport_name_p (oldname)) 15590075Sobrien return; /* already done */ 15690075Sobrien 15790075Sobrien /* ??? One can well ask why we're making these checks here, 15890075Sobrien and that would be a good question. */ 15990075Sobrien 16090075Sobrien /* Imported variables can't be initialized. */ 16190075Sobrien if (TREE_CODE (decl) == VAR_DECL 16290075Sobrien && !DECL_VIRTUAL_P (decl) 16390075Sobrien && DECL_INITIAL (decl)) 16490075Sobrien { 165169689Skan error ("initialized variable %q+D is marked dllimport", decl); 16690075Sobrien return; 16790075Sobrien } 16890075Sobrien /* Nor can they be static. */ 16990075Sobrien if (TREE_CODE (decl) == VAR_DECL 17090075Sobrien /* ??? Is this test for vtables needed? */ 17190075Sobrien && !DECL_VIRTUAL_P (decl) 17290075Sobrien && 0 /*???*/) 17390075Sobrien { 174169689Skan error ("static variable %q+D is marked dllimport", decl); 17590075Sobrien return; 17690075Sobrien } 17790075Sobrien 17890075Sobrien /* `extern' needn't be specified with dllimport. 17990075Sobrien Specify `extern' now and hope for the best. Sigh. */ 18090075Sobrien if (TREE_CODE (decl) == VAR_DECL 18190075Sobrien /* ??? Is this test for vtables needed? */ 18290075Sobrien && !DECL_VIRTUAL_P (decl)) 18390075Sobrien { 18490075Sobrien DECL_EXTERNAL (decl) = 1; 18590075Sobrien TREE_PUBLIC (decl) = 1; 18690075Sobrien } 18790075Sobrien 18890075Sobrien newname = alloca (strlen (oldname) + 11); 18990075Sobrien sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname); 19090075Sobrien 19190075Sobrien /* We pass newname through get_identifier to ensure it has a unique 19290075Sobrien address. RTL processing can sometimes peek inside the symbol ref 19390075Sobrien and compare the string's addresses to see if two symbols are 19490075Sobrien identical. */ 19590075Sobrien /* ??? At least I think that's why we do this. */ 19690075Sobrien idp = get_identifier (newname); 19790075Sobrien 198169689Skan newrtl = gen_rtx_MEM (Pmode, 199169689Skan gen_rtx_SYMBOL_REF (Pmode, 200169689Skan IDENTIFIER_POINTER (idp))); 20190075Sobrien XEXP (DECL_RTL (decl), 0) = newrtl; 20290075Sobrien} 20390075Sobrien 20490075Sobrienvoid 205132718Skanarm_pe_encode_section_info (decl, rtl, first) 20690075Sobrien tree decl; 207132718Skan rtx rtl; 208117395Skan int first ATTRIBUTE_UNUSED; 20990075Sobrien{ 210117395Skan /* This bit is copied from arm_encode_section_info. */ 211169689Skan if (optimize > 0 && TREE_CONSTANT (decl)) 212132718Skan SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; 21390075Sobrien 21490075Sobrien /* Mark the decl so we can tell from the rtl whether the object is 21590075Sobrien dllexport'd or dllimport'd. */ 21690075Sobrien if (arm_dllexport_p (decl)) 21790075Sobrien arm_mark_dllexport (decl); 21890075Sobrien else if (arm_dllimport_p (decl)) 21990075Sobrien arm_mark_dllimport (decl); 22090075Sobrien /* It might be that DECL has already been marked as dllimport, but a 22190075Sobrien subsequent definition nullified that. The attribute is gone but 22290075Sobrien DECL_RTL still has @i.__imp_foo. We need to remove that. */ 22390075Sobrien else if ((TREE_CODE (decl) == FUNCTION_DECL 22490075Sobrien || TREE_CODE (decl) == VAR_DECL) 22590075Sobrien && DECL_RTL (decl) != NULL_RTX 22690075Sobrien && GET_CODE (DECL_RTL (decl)) == MEM 22790075Sobrien && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM 22890075Sobrien && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF 22990075Sobrien && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) 23090075Sobrien { 23190075Sobrien const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); 23290075Sobrien tree idp = get_identifier (oldname + 9); 233169689Skan rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 23490075Sobrien 23590075Sobrien XEXP (DECL_RTL (decl), 0) = newrtl; 23690075Sobrien 23790075Sobrien /* We previously set TREE_PUBLIC and DECL_EXTERNAL. 23890075Sobrien ??? We leave these alone for now. */ 23990075Sobrien } 24090075Sobrien} 24190075Sobrien 24290075Sobrienvoid 24390075Sobrienarm_pe_unique_section (decl, reloc) 24490075Sobrien tree decl; 24590075Sobrien int reloc; 24690075Sobrien{ 24790075Sobrien int len; 24890075Sobrien const char * name; 24990075Sobrien char * string; 25090075Sobrien const char * prefix; 25190075Sobrien 25290075Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 253117395Skan name = arm_strip_name_encoding (name); 25490075Sobrien 25590075Sobrien /* The object is put in, for example, section .text$foo. 25690075Sobrien The linker will then ultimately place them in .text 25790075Sobrien (everything from the $ on is stripped). */ 25890075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 25990075Sobrien prefix = ".text$"; 260117395Skan else if (decl_readonly_section (decl, reloc)) 26190075Sobrien prefix = ".rdata$"; 26290075Sobrien else 26390075Sobrien prefix = ".data$"; 26490075Sobrien len = strlen (name) + strlen (prefix); 26590075Sobrien string = alloca (len + 1); 26690075Sobrien sprintf (string, "%s%s", prefix, name); 26790075Sobrien 26890075Sobrien DECL_SECTION_NAME (decl) = build_string (len, string); 26990075Sobrien} 270