June 16, 2021
On Wednesday, 16 June 2021 at 22:16:54 UTC, H. S. Teoh wrote:
> The compiler does not (and cannot) know.  But the runtime dynamic linker can, and does.  The two are bridged by the compiler emitting a relocatable symbol for the address of the global variable, with a table of relocations (offsets in the code) that the runtime linker patches the actual addresses into when the program is executed.
>
>
> T

Exactly! Except that the dynamic linker is not really involved here, since all the symbols can/must be relocated statically at link time.
June 16, 2021
On 6/16/21 3:27 PM, Doeme wrote:
> On Wednesday, 16 June 2021 at 22:16:54 UTC, H. S. Teoh wrote:
>> The compiler does not (and cannot) know.  But the runtime dynamic linker can, and does.  The two are bridged by the compiler emitting a relocatable symbol for the address of the global variable, with a table of relocations (offsets in the code) that the runtime linker patches the actual addresses into when the program is executed.
>>
>>
>> T
> 
> Exactly! Except that the dynamic linker is not really involved here, since all the symbols can/must be relocated statically at link time.

Thank you, both. It still rules out an address at "compile time" in general. For example, we cannot use such an address when instantiating a template, or static array length, etc.

And if I understand it correctly, there must be a pointer *variable* for the linker to initialize. Fine then: That's how this usage works for C but not for D. :)

Thank you,
Ali

June 17, 2021

On Wednesday, 16 June 2021 at 23:20:26 UTC, Ali Çehreli wrote:

>

Thank you, both. It still rules out an address at "compile time" in general. For example, we cannot use such an address when instantiating a template, or static array length, etc.

And if I understand it correctly, there must be a pointer variable for the linker to initialize. Fine then: That's how this usage works for C but not for D. :)

Thank you,
Ali

Yes, there must be a pointer variable, which explains why we can not do compile time pointer arithmetic, which is fair and square (although I think it might be possible with some extra compiler effort). It does not explain why we can't take addresses of struct members, though, since we have a pointer variable there!

Coming back to the working part of my first example:

struct Foo{
	int bar;
}

__gshared Foo foo;
void *fooptr = &foo;

This works! And yields very similar relocations than the C version (plus some overhead and name-mangling):


[...]

0000000000000000  w    O .data._D19TypeInfo_S4test3Foo6__initZ	0000000000000091 _D19TypeInfo_S4test3Foo6__initZ
0000000000000000 g     O .bss	0000000000000004 _D4test3Foo6__initZ
0000000000000004 g     O .bss	0000000000000004 _D4test3fooSQk3Foo
0000000000000000 g       .tdata.	0000000000000008 _D4test6fooptrPv
0000000000000000 g     O .rodata	000000000000000d _D4test12__ModuleInfoZ

[...]

RELOCATION RECORDS FOR [.tdata.]:
OFFSET           TYPE              VALUE
0000000000000000 R_X86_64_64       _D4test3fooSQk3Foo

[...]

The only difference is that the compiler will not pass down relocations plus an offset (i.e. relocating to a member of a struct) down to the linker, and I don't quite see a specific reason why it should not.

1 2
Next ›   Last »