This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Updated] dllimport/dllexport attributes for Win32/BeOS
- To: Jeffrey A Law <law at cygnus dot com>
- Subject: Re: [Updated] dllimport/dllexport attributes for Win32/BeOS
- From: Mumit Khan <khan at xraylith dot wisc dot edu>
- Date: Thu, 25 Jun 1998 12:52:10 -0500 (CDT)
- Cc: egcs-patches at cygnus dot com
On Thu, 25 Jun 1998, Jeffrey A Law wrote:
> > Index: gcc/tree.c
> > ===================================================================
> > RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.c,v
> > retrieving revision 1.33
> > diff -u -3 -p -r1.33 tree.c
> > --- tree.c 1998/06/20 00:35:42 1.33
> > +++ tree.c 1998/06/22 23:48:53
> > @@ -2256,10 +2256,26 @@ staticp (arg)
> > switch (TREE_CODE (arg))
> > {
> > case FUNCTION_DECL:
> > + /* Don't treat global scope DLL imported functions as static since
> > + taking their address involves initialization. */
> > + if (global_bindings_p ()
> > + && lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES(arg))
> > + != NULL_TREE)
> > + {
> > + return 0;
> > + }
> This is pretty hokey. You're checking a machine dependent attribute
> in generic code. We'd be better off making the attribute a first class
> attribute instead of a machine dependent attribute.
Yes, it is hokey, but I don't know of a better way to do this.
On Win32, variables and functions imported from a DLL need to be accessed
indirectly. For example, the following are equivalent:
__attribute__((dllimport)) int impvar; // note implicit extern.
and
extern int (*__imp_impvar);
This patch creates a new MEM when it sees the dllimport attribute, and user
code can use it transparently as "impvar" instead of having to access it
via the pointers (cf: i386/winnt.c (i386_pe_mark_dllimport)).
Now take the following case:
// file scope. The Initialization is illegal ANSI C, but valid C++.
__attribute__((dllimport)) int impvar; // note implicit extern.
int *i = &impvar;
Here the parser sees "&impvar" and finish_decl/cp_finish_decl eventually
calls build_unary_op with ADDR_EXPR as the code. So far so good. Now
looks at the following comment in build_unary_op (used by both C and C++):
/* Address of a static or external variable or
function counts as a constant. */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
This doesn't work since we've munged the RTL, and can't treat &impvar as
an address constant (assembly will fail). Somehow we need to tell the
backend that it requires initialization, and not a constant. Hence the
test in staticp(), which returns non-constant when we're dealing with
taking addresses of imported decls. The global scope test shouldn't be
needed, but I was just playing safe.
I could do this with REFERENCE_TYPE, but it opens another can of worms
(MS has re-definition rules, and once the types are changed to
references, it doesn't work any more). Ditto for auto-coercion into a
pointer. The redefinitions rules are illustrated already in the gcc
testsuite for ARM/PE (see dll-?.c files).
>
> I'm also a little confused about why these would be considered static
> to begin with since apparently they're "global scope"? Can you give
> me a little more background on what's going on?
>
"static" in the storage sense, not C sense; see the comment in staticp().
Suggestions/fixes more than welcome.
Mumit