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