📄 winnt.c
字号:
/* Subroutines for insn-output.c for Windows NT. Contributed by Douglas Rupp (drupp@cs.washington.edu) Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING. If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "output.h"#include "tree.h"#include "flags.h"#include "tm_p.h"#include "toplev.h"#include "hashtab.h"#include "ggc.h"/* i386/PE specific attribute support. i386/PE has two new attributes: dllexport - for exporting a function/variable that will live in a dll dllimport - for importing a function/variable from a dll Microsoft allows multiple declspecs in one __declspec, separating them with spaces. We do NOT support this. Instead, use __declspec multiple times.*/static tree associated_type (tree);static tree gen_stdcall_or_fastcall_suffix (tree, bool);static int i386_pe_dllexport_p (tree);static int i386_pe_dllimport_p (tree);static void i386_pe_mark_dllexport (tree);static void i386_pe_mark_dllimport (tree);/* This is we how mark internal identifiers with dllimport or dllexport attributes. */#ifndef DLL_IMPORT_PREFIX#define DLL_IMPORT_PREFIX "#i."#endif#ifndef DLL_EXPORT_PREFIX#define DLL_EXPORT_PREFIX "#e."#endif/* Handle a "shared" attribute; arguments as in struct attribute_spec.handler. */treeix86_handle_shared_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs){ if (TREE_CODE (*node) != VAR_DECL) { warning ("%qs attribute only applies to variables", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE;}/* Return the type that we should use to determine if DECL is imported or exported. */static treeassociated_type (tree decl){ tree t = NULL_TREE; /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer to the containing class. So we look at the 'this' arg. */ if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) { /* Artificial methods are not affected by the import/export status of their class unless they are COMDAT. Implicit copy ctor's and dtor's are not affected by class status but virtual and non-virtual thunks are. */ if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl)) t = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); } else if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) t = DECL_CONTEXT (decl); return t;}/* Return nonzero if DECL is a dllexport'd object. */static inti386_pe_dllexport_p (tree decl){ tree exp; if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); if (exp) return 1; /* Class members get the dllexport status of their class. */ if (associated_type (decl)) { exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (associated_type (decl))); if (exp) return 1; } return 0;}/* Return nonzero if DECL is a dllimport'd object. */static inti386_pe_dllimport_p (tree decl){ tree imp; int context_imp = 0; if (TREE_CODE (decl) == FUNCTION_DECL && TARGET_NOP_FUN_DLLIMPORT) return 0; if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); /* Class members get the dllimport status of their class. */ if (!imp && associated_type (decl)) { imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (associated_type (decl))); if (imp) context_imp = 1; } if (imp) { /* Don't mark defined functions as dllimport. If the definition itself was marked with dllimport, than ix86_handle_dll_attribute reports an error. This handles the case when the definition overrides an earlier declaration. */ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) && !DECL_INLINE (decl)) { /* Don't warn about artificial methods. */ if (!DECL_ARTIFICIAL (decl)) warning ("%Jfunction '%D' is defined after prior declaration " "as dllimport: attribute ignored", decl, decl); return 0; } /* We ignore the dllimport attribute for inline member functions. This differs from MSVC behavior which treats it like GNUC 'extern inline' extension. */ else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) { if (extra_warnings) warning ("%Jinline function '%D' is declared as dllimport: " "attribute ignored.", decl, decl); return 0; } /* Don't allow definitions of static data members in dllimport class, Just ignore attribute for vtable data. */ else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl) && context_imp) { if (!DECL_VIRTUAL_P (decl)) error ("%Jdefinition of static data member '%D' of " "dllimport'd class.", decl, decl); return 0; } /* Since we can't treat a pointer to a dllimport'd symbol as a constant address, we turn off the attribute on C++ virtual methods to allow creation of vtables using thunks. Don't mark artificial methods either (in associated_type, only COMDAT artificial method get import status from class context). */ else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl))) return 0; return 1; } return 0;}/* Return nonzero if SYMBOL is marked as being dllexport'd. */inti386_pe_dllexport_name_p (const char *symbol){ return (strncmp (DLL_EXPORT_PREFIX, symbol, strlen (DLL_EXPORT_PREFIX)) == 0);}/* Return nonzero if SYMBOL is marked as being dllimport'd. */inti386_pe_dllimport_name_p (const char *symbol){ return (strncmp (DLL_IMPORT_PREFIX, symbol, strlen (DLL_IMPORT_PREFIX)) == 0);}/* Mark a DECL as being dllexport'd. Note that we override the previous setting (e.g.: dllimport). */static voidi386_pe_mark_dllexport (tree decl){ const char *oldname; char *newname; rtx rtlname; rtx symref; tree idp; rtlname = XEXP (DECL_RTL (decl), 0); if (GET_CODE (rtlname) == SYMBOL_REF) oldname = XSTR (rtlname, 0); else if (GET_CODE (rtlname) == MEM && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) oldname = XSTR (XEXP (rtlname, 0), 0); else abort (); if (i386_pe_dllimport_name_p (oldname)) { warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.", decl, decl); /* Remove DLL_IMPORT_PREFIX. */ oldname += strlen (DLL_IMPORT_PREFIX); DECL_NON_ADDR_CONST_P (decl) = 0; } else if (i386_pe_dllexport_name_p (oldname)) return; /* already done */ newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname); /* We pass newname through get_identifier to ensure it has a unique address. RTL processing can sometimes peek inside the symbol ref and compare the string's addresses to see if two symbols are identical. */ idp = get_identifier (newname); symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); SYMBOL_REF_DECL (symref) = decl; XEXP (DECL_RTL (decl), 0) = symref;}/* Mark a DECL as being dllimport'd. */static voidi386_pe_mark_dllimport (tree decl){ const char *oldname; char *newname; tree idp; rtx rtlname, newrtl; rtx symref; rtlname = XEXP (DECL_RTL (decl), 0); if (GET_CODE (rtlname) == SYMBOL_REF) oldname = XSTR (rtlname, 0); else if (GET_CODE (rtlname) == MEM && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) oldname = XSTR (XEXP (rtlname, 0), 0); else abort (); if (i386_pe_dllexport_name_p (oldname)) { error ("%qs declared as both exported to and imported from a DLL", IDENTIFIER_POINTER (DECL_NAME (decl))); return; } else if (i386_pe_dllimport_name_p (oldname)) { /* Already done, but do a sanity check to prevent assembler errors. */ if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) { error ("%Jfailure in redeclaration of '%D': dllimport'd " "symbol lacks external linkage.", decl, decl); abort(); } return; } newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); /* We pass newname through get_identifier to ensure it has a unique address. RTL processing can sometimes peek inside the symbol ref and compare the string's addresses to see if two symbols are identical. */ idp = get_identifier (newname); symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); SYMBOL_REF_DECL (symref) = decl; newrtl = gen_rtx_MEM (Pmode,symref); XEXP (DECL_RTL (decl), 0) = newrtl; /* Can't treat a pointer to this as a constant address */ DECL_NON_ADDR_CONST_P (decl) = 1;}/* Return string which is the former assembler name modified with a suffix consisting of an atsign (@) followed by the number of bytes of arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */static treegen_stdcall_or_fastcall_suffix (tree decl, bool fastcall){ int total = 0; /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead of DECL_ASSEMBLER_NAME. */ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); char *newsym; char *p; tree formal_type; /* Do not change the identifier if a verbatim asmspec or already done. */ if (*asmname == '*' || strchr (asmname, '@')) return DECL_ASSEMBLER_NAME (decl); formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); if (formal_type != NULL_TREE) { /* These attributes are ignored for variadic functions in i386.c:ix86_return_pops_args. For compatibility with MS compiler do not add @0 suffix here. */ if (TREE_VALUE (tree_last (formal_type)) != void_type_node) return DECL_ASSEMBLER_NAME (decl); /* Quit if we hit an incomplete type. Error is reported by convert_arguments in c-typeck.c or cp/typeck.c. */ while (TREE_VALUE (formal_type) != void_type_node && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) { int parm_size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); /* Must round up to include padding. This is done the same way as in store_one_arg. */ parm_size = ((parm_size + PARM_BOUNDARY - 1) / PARM_BOUNDARY * PARM_BOUNDARY); total += parm_size; formal_type = TREE_CHAIN (formal_type);\ } } /* Assume max of 8 base 10 digits in the suffix. */ newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); p = newsym; if (fastcall) *p++ = FASTCALL_PREFIX; sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT); return get_identifier (newsym);}voidi386_pe_encode_section_info (tree decl, rtx rtl, int first){ default_encode_section_info (decl, rtl, first);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -