Note about Cygwin dll ports.

Gauche heavily relies on the link-time relocation of variable
references.  That is, Gauche uses the address of the ScmClass
structure as the type tag of objects, and statically declared
objects has a reference to them.   On unix, the dynamic-linker
resolves this reference at the time the DSO file is loaded.


    Gauche object                   Gauche class
  +----------------+            (may be in another .so)
  |  class tag    -------------> +-----------------+
  +----------------+             |                 |
  |  ...           |             |                 |
  |                |             |                 |
  +----------------+             +-----------------+

This works quite nicely.   It has those characteristics.

  * You can add a class without "registering" it to
    the global class table to obtain a unique class tag.
    Just define a class, and it is immediately available
    to be used as a class tag.

  * Since you don't need to refer to the run-time tag table,
    you can have static reference to the classes.  Such as
    arrays of inherited classes or arrays of classes for
    method arguments.

On Win32, dynamic linker is not so smart.  Instead of scanning
entire code to rewrite those external references, it allocates
indirect pointer table at the compilation time, and the linker
just rewrites the table.   If the ScmClass structure is in the
other DLL, it works like this:

    Gauche object
  +----------------+
  |  class tag -------\
  +----------------+  |
  |  ...           |  |
  |                |  |
  +----------------+  |
                      |
    relocation table  |
   (in the same dll)  |                 Gauche class
  +----------------+<-/              (in the different dll)
  |                |---------------->+------------------+
  +----------------+                 |                  |
                                     +------------------+


Of course this doesn't work as is, for we have one more pointer
indirection (note that the function call to the external dll
works fine, since the relocation table actually contains a jump
instruction to the real entry).   So you have to declare the
data in external dlls as "__declspec(dllimport)", and then
the compiler treats the variable as if they are pointers.

For example, if the source is like this:

   extern __declspec(dllimport) int var_in_ext_dll;

   foo() {
       int x = var_in_ext_dll;
       int *y = &var_in_ext_dll;
   }

It is actually compiled as if:

   extern int *_imp__var_in_ext_dll;

   foo() {
       int x = *_imp__var_in_ext_dll;
       int *y = _imp__var_in_ext_dll;
   }

In case of Gauche's type tag, the source is something like this:

   extern __declspec(dllimport) ScmClass ScmFooClass;

   static ScmFoo foo = {{&ScmFooClass}, ...};

and it is compiled as if:

   extern ScmClass *_imp__ScmFooClass;

   static ScmFoo foo = {{_imp__ScmFooClass}, ...};

Now, the problem is that the value of _imp__ScmFooClass
can't be determined until the dynamic-link time, so it can't
be used in the static initializer.

Currently there are three places where the static reference
to the address of the class structure.

 * Static declaration of Scheme objects, including ScmClass,
   ScmString, ScmSubr, ScmSyntax, etc.
 * Static declaration of class precedence array, to be used
   to initialize ScmClass statically.
 * Static declaration of method specializer array, to be used
   to initialize ScmMethod statically.

Furthermore, the addresses of the classes (e.g. &ScmPairClass)
are scattered in the sources (by the form of macros, such as
SCM_CLASS_PAIR).

I feel the original design of "class pointer as a tag" is
clean and simple, and don't want to obscure the architecture
by cluttering #ifdef's and nested macro calls just to port
Gauche to Win32.   So these are the changes I made for Cygwin
version:

  1. A class tag for each object becomes double-indirect
     pointer to ScmClass.   The access to the tag field should
     be done via macros (SCM_CLASS_OF and SCM_SET_CLASS) and
     this change is hidden in them.

  2. SCM_CLASS_FOO macro remains to be &ScmFooClass.

  3. For static initializers, a programmer should use
     SCM_CLASS_PTR(ScmFooClass) instead of SCM_CLASS_FOO.

  4. For class precedence array and method specializer array,
     Initialization methods convert ScmClass** array to 
     ScmClass* array.

So, for cygwin environment only, the source will look
like this after macro expansion.

   extern __declspec(dllimport) ScmClass ScmFooClass;
   extern ScmClass *_imp__ScmFooClass;

   typedef ScmHeaderRec {
       ScmClass *klass;
   } ScmHeader;

   static ScmFoo foo = {{(ScmClass*)&_imp__ScmFooClass}, ... };

Note that although _imp__ScmFooClass is declared as "extern", 
its scope is actually just inside a single DLL, or a statically 
linked executable.   So for the different DLLs, &_imp__ScmFooClass
differs.  It is automatically initialized to point to the variable
ScmFooClass, which actually resides in the DLL where it is defined.
The body of _imp__ScmFooClass is automatically allocated by the
linker.


