Commit 27da1b4d by Mumit Khan Committed by Jeff Law

Support for dllimport and dllexport attributes for i386-pe.

	* tree.h (DECL_NON_ADDR_CONST_P): New accessor macro.
	(struct tree_decl): Add non_addr_const_p field.
	* tree.c (staticp): Use.
	* i386/cygwin32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
	attributes.
	(SUBTARGET_SWITCHES): Switches to turn on/off dllimport|export
	attributes. Also accept -mwindows option.
	(VALID_MACHINE_DECL_ATTRIBUTE): New macro.
	(MERGE_MACHINE_DECL_ATTRIBUTE): New macro.
	(REDO_SECTION_INFO_P): New macro.
	(DRECTVE_SECTION_FUNCTION): New macro.
	(drectve_section): Cover function to implement above.
	(SWITCH_TO_SECTION_FUNCTION): New macro.
	(switch_to_section): Covert function to implement above.
	(EXTRA_SECTIONS): Add in_drectve.
	(EXTRA_SECTION_FUNCTIONS): Add in_drectve and switch_to_section.
	(ENCODE_SECTION_INFO): Delete old macro and redefine as a function.
	(STRIP_NAME_ENCODING): Handle new attributes.
	(ASM_OUTPUT_LABELREF): New macro.
	(ASM_OUTPUT_FUNCTION_NAME): New macro.
	(ASM_OUTPUT_COMMON): New macro.
	(ASM_OUTPUT_DECLARE_OBJECT_NAME): New macro.
	* i386/mingw32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
	attributes.
	* i386/winnt.c (i386_pe_valid_decl_attribute_p): New function.
	(i386_pe_merge_decl_attributes): New function.
	(i386_pe_check_vtable_importexport): New function.
	(i386_pe_dllexport_p): New function.
	(i386_pe_dllimport_p): New function.
	(i386_pe_dllexport_name_p): New function.
	(i386_pe_dllimport_name_p): New function.
	(i386_pe_mark_dllexport): New function.
	(i386_pe_mark_dllimport): New function.
	(i386_pe_encode_section_info): New function.
	(i386_pe_unique_section): Strip encoding from name first.

From-SVN: r20983
parent bceb30e7
Tue Jul 7 01:03:03 1998 Mumit Khan <khan@xraylith.wisc.edu>
Support for dllimport and dllexport attributes for i386-pe.
* tree.h (DECL_NON_ADDR_CONST_P): New accessor macro.
(struct tree_decl): Add non_addr_const_p field.
* tree.c (staticp): Use.
* i386/cygwin32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
attributes.
(SUBTARGET_SWITCHES): Switches to turn on/off dllimport|export
attributes. Also accept -mwindows option.
(VALID_MACHINE_DECL_ATTRIBUTE): New macro.
(MERGE_MACHINE_DECL_ATTRIBUTE): New macro.
(REDO_SECTION_INFO_P): New macro.
(DRECTVE_SECTION_FUNCTION): New macro.
(drectve_section): Cover function to implement above.
(SWITCH_TO_SECTION_FUNCTION): New macro.
(switch_to_section): Covert function to implement above.
(EXTRA_SECTIONS): Add in_drectve.
(EXTRA_SECTION_FUNCTIONS): Add in_drectve and switch_to_section.
(ENCODE_SECTION_INFO): Delete old macro and redefine as a function.
(STRIP_NAME_ENCODING): Handle new attributes.
(ASM_OUTPUT_LABELREF): New macro.
(ASM_OUTPUT_FUNCTION_NAME): New macro.
(ASM_OUTPUT_COMMON): New macro.
(ASM_OUTPUT_DECLARE_OBJECT_NAME): New macro.
* i386/mingw32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
attributes.
* i386/winnt.c (i386_pe_valid_decl_attribute_p): New function.
(i386_pe_merge_decl_attributes): New function.
(i386_pe_check_vtable_importexport): New function.
(i386_pe_dllexport_p): New function.
(i386_pe_dllimport_p): New function.
(i386_pe_dllexport_name_p): New function.
(i386_pe_dllimport_name_p): New function.
(i386_pe_mark_dllexport): New function.
(i386_pe_mark_dllimport): New function.
(i386_pe_encode_section_info): New function.
(i386_pe_unique_section): Strip encoding from name first.
Tue Jul 7 00:50:17 1998 Manfred Hollstein (manfred@s-direktnet.de) Tue Jul 7 00:50:17 1998 Manfred Hollstein (manfred@s-direktnet.de)
* libgcc2.c (L_exit): Provide a fake for atexit on systems which * libgcc2.c (L_exit): Provide a fake for atexit on systems which
......
...@@ -30,6 +30,14 @@ Boston, MA 02111-1307, USA. */ ...@@ -30,6 +30,14 @@ Boston, MA 02111-1307, USA. */
#include "i386/gas.h" #include "i386/gas.h"
#include "dbxcoff.h" #include "dbxcoff.h"
/* Support the __declspec keyword by turning them into attributes.
We currently only support: dllimport and dllexport.
Note that the current way we do this may result in a collision with
predefined attributes later on. This can be solved by using one attribute,
say __declspec__, and passing args to it. The problem with that approach
is that args are not accumulated: each new appearance would clobber any
existing args. */
#ifdef CPP_PREDEFINES #ifdef CPP_PREDEFINES
#undef CPP_PREDEFINES #undef CPP_PREDEFINES
#endif #endif
...@@ -38,6 +46,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -38,6 +46,7 @@ Boston, MA 02111-1307, USA. */
-D__CYGWIN32__ -DWINNT -D_X86_=1 -D__STDC__=1\ -D__CYGWIN32__ -DWINNT -D_X86_=1 -D__STDC__=1\
-D__stdcall=__attribute__((__stdcall__)) \ -D__stdcall=__attribute__((__stdcall__)) \
-D__cdecl=__attribute__((__cdecl__)) \ -D__cdecl=__attribute__((__cdecl__)) \
-D__declspec(x)=__attribute__((x)) \
-Asystem(winnt) -Acpu(i386) -Amachine(i386)" -Asystem(winnt) -Acpu(i386) -Amachine(i386)"
#undef CPP_SPEC #undef CPP_SPEC
...@@ -69,13 +78,51 @@ Boston, MA 02111-1307, USA. */ ...@@ -69,13 +78,51 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE "short unsigned int" #define WCHAR_TYPE "short unsigned int"
#define HAVE_ATEXIT 1 #define HAVE_ATEXIT 1
/* Ignore dllimport for functions. */
#define TARGET_NOP_FUN_DLLIMPORT (target_flags & 0x20000)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{ "nop-fun-dllimport", 0x20000 }, \
{ "no-nop-fun-dllimport", -0x20000 }, \
{ "windows", 0x0 },
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
extern int i386_pe_valid_decl_attribute_p ();
#undef VALID_MACHINE_DECL_ATTRIBUTE
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
i386_pe_valid_decl_attribute_p (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
extern union tree_node *i386_pe_merge_decl_attributes ();
#define MERGE_MACHINE_DECL_ATTRIBUTES(OLD, NEW) \
i386_pe_merge_decl_attributes ((OLD), (NEW))
/* Used to implement dllexport overriding dllimport semantics. It's also used
to handle vtables - the first pass won't do anything because
DECL_CONTEXT (DECL) will be 0 so i386_pe_dll{ex,im}port_p will return 0.
It's also used to handle dllimport override semantics. */
#if 0
#define REDO_SECTION_INFO_P(DECL) \
((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
#else
#define REDO_SECTION_INFO_P(DECL) 1
#endif
#undef EXTRA_SECTIONS #undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_ctor, in_dtor #define EXTRA_SECTIONS in_ctor, in_dtor, in_drectve
#undef EXTRA_SECTION_FUNCTIONS #undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \ #define EXTRA_SECTION_FUNCTIONS \
CTOR_SECTION_FUNCTION \ CTOR_SECTION_FUNCTION \
DTOR_SECTION_FUNCTION DTOR_SECTION_FUNCTION \
DRECTVE_SECTION_FUNCTION \
SWITCH_TO_SECTION_FUNCTION
#define CTOR_SECTION_FUNCTION \ #define CTOR_SECTION_FUNCTION \
void \ void \
...@@ -99,6 +146,41 @@ dtor_section () \ ...@@ -99,6 +146,41 @@ dtor_section () \
} \ } \
} }
#define DRECTVE_SECTION_FUNCTION \
void \
drectve_section () \
{ \
if (in_section != in_drectve) \
{ \
fprintf (asm_out_file, "%s\n", "\t.section .drectve\n"); \
in_section = in_drectve; \
} \
}
/* Switch to SECTION (an `enum in_section').
??? This facility should be provided by GCC proper.
The problem is that we want to temporarily switch sections in
ASM_DECLARE_OBJECT_NAME and then switch back to the original section
afterwards. */
#define SWITCH_TO_SECTION_FUNCTION \
void \
switch_to_section (section, decl) \
enum in_section section; \
tree decl; \
{ \
switch (section) \
{ \
case in_text: text_section (); break; \
case in_data: data_section (); break; \
case in_named: named_section (decl, NULL, 0); break; \
case in_ctor: ctor_section (); break; \
case in_dtor: dtor_section (); break; \
case in_drectve: drectve_section (); break; \
default: abort (); break; \
} \
}
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \ do { \
ctor_section (); \ ctor_section (); \
...@@ -111,7 +193,7 @@ dtor_section () \ ...@@ -111,7 +193,7 @@ dtor_section () \
do { \ do { \
dtor_section (); \ dtor_section (); \
fprintf (FILE, "%s\t", ASM_LONG); \ fprintf (FILE, "%s\t", ASM_LONG); \
assemble_name (FILE, NAME); \ assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \ fprintf (FILE, "\n"); \
} while (0) } while (0)
...@@ -119,44 +201,38 @@ dtor_section () \ ...@@ -119,44 +201,38 @@ dtor_section () \
differently depending on something about the variable or differently depending on something about the variable or
function named by the symbol (such as what section it is in). function named by the symbol (such as what section it is in).
On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
so that we may access it directly in the GOT.
On i386 running Windows NT, modify the assembler name with a suffix On i386 running Windows NT, modify the assembler name with a suffix
consisting of an atsign (@) followed by string of digits that represents consisting of an atsign (@) followed by string of digits that represents
the number of bytes of arguments passed to the function, if it has the the number of bytes of arguments passed to the function, if it has the
attribute STDCALL. */ attribute STDCALL.
In addition, we must mark dll symbols specially. Definitions of
dllexport'd objects install some info in the .drectve section.
References to dllimport'd objects are fetched indirectly via
_imp__. If both are declared, dllexport overrides. This is also
needed to implement one-only vtables: they go into their own
section and we need to set DECL_SECTION_NAME so we do that here.
Note that we can be called twice on the same decl. */
extern void i386_pe_encode_section_info ();
#ifdef ENCODE_SECTION_INFO #ifdef ENCODE_SECTION_INFO
#undef ENCODE_SECTION_INFO #undef ENCODE_SECTION_INFO
#define ENCODE_SECTION_INFO(DECL) \
do \
{ \
if (flag_pic) \
{ \
rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
= (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
|| ! TREE_PUBLIC (DECL)); \
} \
if (TREE_CODE (DECL) == FUNCTION_DECL) \
if (lookup_attribute ("stdcall", \
TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
XEXP (DECL_RTL (DECL), 0) = \
gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
} \
while (0)
#endif #endif
#define ENCODE_SECTION_INFO(DECL) i386_pe_encode_section_info (DECL)
/* This macro gets just the user-specified name out of the string in a /* Utility used only in this file. */
SYMBOL_REF. Discard trailing @[NUM] encoded by ENCODE_SECTION_INFO. */ #define I386_PE_STRIP_ENCODING(SYM_NAME) \
((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
/* This macro gets just the user-specified name
out of the string in a SYMBOL_REF. Discard
trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
#undef STRIP_NAME_ENCODING #undef STRIP_NAME_ENCODING
#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
do { \ do { \
char *_p; \ char *_p; \
char *_name = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')); \ char *_name = I386_PE_STRIP_ENCODING (SYMBOL_NAME); \
for (_p = _name; *_p && *_p != '@'; ++_p) \ for (_p = _name; *_p && *_p != '@'; ++_p) \
; \ ; \
if (*_p == '@') \ if (*_p == '@') \
...@@ -170,6 +246,62 @@ do { \ ...@@ -170,6 +246,62 @@ do { \
(VAR) = _name; \ (VAR) = _name; \
} while (0) } while (0)
/* Output a reference to a label. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, \
I386_PE_STRIP_ENCODING (NAME)) \
/* Output a function definition label. */
#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
do { \
if (i386_pe_dllexport_name_p (NAME)) \
{ \
drectve_section (); \
fprintf ((STREAM), "\t.ascii \" -export:%s\"\n", \
I386_PE_STRIP_ENCODING (NAME)); \
function_section (DECL); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0)
/* Output a common block. */
#undef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
do { \
if (i386_pe_dllexport_name_p (NAME)) \
{ \
drectve_section (); \
fprintf ((STREAM), "\t.ascii \" -export:%s\"\n", \
I386_PE_STRIP_ENCODING (NAME)); \
} \
if (! i386_pe_dllimport_name_p (NAME)) \
{ \
fprintf ((STREAM), "\t.comm\t"); \
assemble_name ((STREAM), (NAME)); \
fprintf ((STREAM), ", %d\t%s %d\n", \
(ROUNDED), ASM_COMMENT_START, (SIZE)); \
} \
} while (0)
/* Output the label for an initialized variable. */
#undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
do { \
if (i386_pe_dllexport_name_p (NAME)) \
{ \
enum in_section save_section = in_section; \
drectve_section (); \
fprintf ((STREAM), "\t.ascii \" -export:%s\"\n", \
I386_PE_STRIP_ENCODING (NAME)); \
switch_to_section (save_section, (DECL)); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0)
/* Emit code to check the stack when allocating more that 4000 /* Emit code to check the stack when allocating more that 4000
bytes in one go. */ bytes in one go. */
......
...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
-D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\ -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\
-D__stdcall=__attribute__((__stdcall__)) \ -D__stdcall=__attribute__((__stdcall__)) \
-D__cdecl=__attribute__((__cdecl__)) \ -D__cdecl=__attribute__((__cdecl__)) \
-D__declspec(x)=__attribute__((x)) \
-Asystem(winnt) -Acpu(i386) -Amachine(i386)" -Asystem(winnt) -Acpu(i386) -Amachine(i386)"
/* Specific a different directory for the standard include files. */ /* Specific a different directory for the standard include files. */
......
...@@ -2265,9 +2265,12 @@ staticp (arg) ...@@ -2265,9 +2265,12 @@ staticp (arg)
case FUNCTION_DECL: case FUNCTION_DECL:
/* Nested functions aren't static, since taking their address /* Nested functions aren't static, since taking their address
involves a trampoline. */ involves a trampoline. */
return decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg); return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
&& ! DECL_NON_ADDR_CONST_P (arg);
case VAR_DECL: case VAR_DECL:
return TREE_STATIC (arg) || DECL_EXTERNAL (arg); return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
&& ! DECL_NON_ADDR_CONST_P (arg);
case CONSTRUCTOR: case CONSTRUCTOR:
return TREE_STATIC (arg); return TREE_STATIC (arg);
......
...@@ -1201,6 +1201,10 @@ struct tree_type ...@@ -1201,6 +1201,10 @@ struct tree_type
#define DECL_LANG_FLAG_6(NODE) (DECL_CHECK (NODE)->decl.lang_flag_6) #define DECL_LANG_FLAG_6(NODE) (DECL_CHECK (NODE)->decl.lang_flag_6)
#define DECL_LANG_FLAG_7(NODE) (DECL_CHECK (NODE)->decl.lang_flag_7) #define DECL_LANG_FLAG_7(NODE) (DECL_CHECK (NODE)->decl.lang_flag_7)
/* Used to indicate that the pointer to this DECL cannot be treated as
an address constant. */
#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p)
struct tree_decl struct tree_decl
{ {
char common[sizeof (struct tree_common)]; char common[sizeof (struct tree_common)];
...@@ -1242,6 +1246,8 @@ struct tree_decl ...@@ -1242,6 +1246,8 @@ struct tree_decl
unsigned lang_flag_6 : 1; unsigned lang_flag_6 : 1;
unsigned lang_flag_7 : 1; unsigned lang_flag_7 : 1;
unsigned non_addr_const_p : 1;
/* For a FUNCTION_DECL, if inline, this is the size of frame needed. /* For a FUNCTION_DECL, if inline, this is the size of frame needed.
If built-in, this is the code for which built-in function. If built-in, this is the code for which built-in function.
For other kinds of decls, this is DECL_ALIGN. */ For other kinds of decls, this is DECL_ALIGN. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment