gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Building GNUstep for Windows using Clang


From: David Chisnall
Subject: Re: Building GNUstep for Windows using Clang
Date: Thu, 21 Jan 2021 14:00:30 +0000
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.6.1

Hi,


On 20/01/2021 20:30, Frederik Seiffert wrote:
There’s one more issue though: both [Test class] and [Test new] (with "Test" 
being defined in the DLL) only return null pointers in my testing. However subclassing 
the Test root class locally works fine and allows instantiating the subclass, as does a 
locally defined root class (same implementation as Test).

The following code (with "Sub" being a subclass of "Test"):

        printf("%p %p\n", [Test class], [Test new]);
        printf("%p %p\n", [Sub class], [Sub new]);

Prints:

        0000000000000000 0000000000000000
        00007FF73EDB0080 00000291D99247A8


Any idea? All other things I tried so far seemed to be working fine, though I’m 
sure this won’t be the last of my questions...

I think I misrememberd some details of the Windows ABI. I wrote a little test compilation unit to look at it:

```obj-c
__attribute__((dllimport))
@interface Test
+ (id)new;
@end

@interface Sub : Test @end

@implementation Sub
+ (id)new
{
        return (void*)1;
}
@end

int main(void)
{
        [Test new];
        [Sub new];
}
```

And compiled it with:

clang11 -S -fobjc-runtime=gnustep-2.0 -target x86_64-pc-windows-msvc -O1 -o - msg.m -emit-llvm

This generates a global like this:

```llvm
@"$_OBJC_CLASS_Test" = external dllimport global i8*
```

This is a dllimport'd global, so one that can be referenced in the instruction stream and will have relocations applied. It can't be referenced in a global and so there's an `.objc_early_init` function generated that initialises the isa pointer of the `Sub` class.

The message sends both directly load from the `_REF_` class pointer, which is declared like this:

```llvm
@"$_OBJC_REF_CLASS_Test" = external dllimport local_unnamed_addr global i8*
```

So this has a canonical home in the DLL that owns the class and every other message send must indirect via that. Without the dllimport qualifier, clang generates:

```llvm
@"$_OBJC_CLASS_Test" = external global i8*
@"$_OBJC_REF_CLASS_Test" = external local_unnamed_addr global i8*
```

These are both local to the DLL or EXE that contains them and won't be correctly initialised.

It looks as if you are missing the dllimport attribute on the classes that you're referencing from another DLL.

In WinObjC, all of the classes are decorated with a macro that does the normal Windows dance of expanding to dllimport normally and dllexport when you are building the DLL that they come from. These are missing from GNUstep, I'm not sure if you added them in your branch.

David






reply via email to

[Prev in Thread] Current Thread [Next in Thread]