Re: Linking with a non-default druntime
On Sunday, 30 September 2018 at 19:03:17 UTC, Per Nordlöw wrote: How can I link my dmd-compiled program with a specific version of the druntime? druntime is within libphobos. So you must change this. I need this when experimenting with a new GC. Did you try what i proposed earlier ? Until the handlers are plugged there can be a fallback to the manual allocs. For example you start with the manual implementation and add handlers + fallback for every functions, like here for malloc ``` __gshared void* function(size_t, uint, const TypeInfo) nothrow mallocHandler; void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow { if (mallocHandler) // experimental stuff { return mallocHandler(size, bits, ti); } else // fallback until handler is assigned { void* p = cstdlib.malloc(size); if (size && p is null) onOutOfMemoryError(); return p; } } ``` this way you can very easily change-compile-test, without recompiling the whole runtime and phobos each time.
Linking with a non-default druntime
How can I link my dmd-compiled program with a specific version of the druntime? I need this when experimenting with a new GC.
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 14:06:20 UTC, Vinod K Chandran wrote: Thanks. It worked. I would like to compile this as a gui. Now it starts with the cmd. Google search didn't gave me the link i want. Any help ? With the default OPTLINK linker: dmd -L/SUBSYSTEM:windows app.d In this case, user32.lib where MessageBoxW and MessageBoxA reside is automatically linked. When using the MS linker: dmd -m64 -L/SUBSYSTEM:windows -L/ENTRY:mainCRTStartup app.d user32.lib In this case, user32.lib is not automatically linked. Replace -m64 with -m32mscoff for 32-bit output with the MS linker. -L passes command line options to the current linker.
Re: inline ASM function calling conventions.
On Sunday, 30 September 2018 at 12:32:08 UTC, kinke wrote: 1) `asm {}` is supported by DMD and LDC, but not by GDC. Good to know. Guess I will be targeting DMD and LDC then. 4) For x86_64, there are 2 (completely different) ABIs, Win64 and the System V one. Specs can be found online. In your case: void Foo(MyStrunct* first_arg, MyStrunct* second_arg) { asm { naked; } version (D_InlineAsm_X86) { // first_arg is on the stack, at [ESP+4] // second_arg is in EAX } else version (D_InlineAsm_X86_64) { version (Win64) { // first_arg is in RDX // second_arg is in RCX } else { // first_arg is in RSI // second_arg is in RDI } } } So in X86 asm, if I want to pas two parameters to a function I can have one in a register, but not two. The second will go via the stack. But on X86_64 it won't? Guess I'll just have to live with that. Thank you!
Re: inline ASM function calling conventions.
On Sunday, 30 September 2018 at 12:07:53 UTC, Basile B. wrote: On Sunday, 30 September 2018 at 11:53:17 UTC, Basile B. wrote: Hello, i think this should be here (https://dlang.org/spec/abi.html) because myself i never remember them correctly without playing a bit with a disassembler. After playing a bit: Thank you for the link, very informative! I'm spitting it through right now. Without all the save/restore BS: module runnable; import std.stdio; alias write4Int = writeln!(int,int,int,int); struct MyStruct{int i;} extern(D) void foo(ref MyStruct s1, ref MyStruct s2, ref MyStruct s3, ref MyStruct s4) { asm { naked; mov RCX, MyStruct.i.offsetof[RCX]; mov RDX, MyStruct.i.offsetof[RDX]; mov RSI, MyStruct.i.offsetof[RSI]; mov RDI, MyStruct.i.offsetof[RDI]; callwrite4Int; ret; } } void main() { MyStruct s1 = MyStruct(1); MyStruct s2 = MyStruct(2); MyStruct s3 = MyStruct(3); MyStruct s4 = MyStruct(4); foo(s1, s2, s3, s4); } In X86_64 it works beautiful! But in X86 it will pass them via the stack, and I'm trying to get rid of that.
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 13:21:59 UTC, Adam D. Ruppe wrote: On Sunday, 30 September 2018 at 13:17:33 UTC, Vinod K Chandran wrote: Thanks for the reply. But it says "toUTFz" is not defined. do i missing any import statement ? import std.utf; Thanks. It worked. I would like to compile this as a gui. Now it starts with the cmd. Google search didn't gave me the link i want. Any help ?
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 13:17:33 UTC, Vinod K Chandran wrote: Thanks for the reply. But it says "toUTFz" is not defined. do i missing any import statement ? import std.utf;
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 13:17:33 UTC, Vinod K Chandran wrote: On Sunday, 30 September 2018 at 12:48:17 UTC, Adam D. Ruppe wrote: so usage is: toUTFz!(wchar*)(your_string_here); If passing string literals to Windows, you can put a w at the end, like: MessageBoxW(null, "Hello"w, "World"w, 0); // note the ""w Thanks for the reply. But it says "toUTFz" is not defined. do i missing any import statement ? I am trying to make this function, but compiler is rejecting all my attempts. ```D int MsgBox(string MsgTxt, string titleTxt = "MessageBox") { const wchar* Mesg = toUTFz! (wchar*)(MsgTxt) ; const wchar* Tit = toUTFz! (wchar*)(itleTxt) ; MessageBoxW(null, Mesg, Tit, 0) ; return 0 ; } ```
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 12:48:17 UTC, Adam D. Ruppe wrote: so usage is: toUTFz!(wchar*)(your_string_here); If passing string literals to Windows, you can put a w at the end, like: MessageBoxW(null, "Hello"w, "World"w, 0); // note the ""w Thanks for the reply. But it says "toUTFz" is not defined. do i missing any import statement ?
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 06:56:41 UTC, bauss wrote: There is function that does it for you called toStringz() https://dlang.org/library/std/string/to_stringz.html Not really best for Windows. That's for calling C functions with char*, for Windows, you should be working with wchar* instead. http://dpldocs.info/experimental-docs/std.utf.toUTFz.html so usage is: toUTFz!(wchar*)(your_string_here); If passing string literals to Windows, you can put a w at the end, like: MessageBoxW(null, "Hello"w, "World"w, 0); // note the ""w
Re: inline ASM function calling conventions.
On Sunday, 30 September 2018 at 10:46:33 UTC, Sjoerd Nijboer wrote: I'm kinda puzzled. I'm having trouble getting started with inline asm in D. Suppowse I have the following: void Foo(MyStrunct* first_arg, MyStrunct* second_arg) { asm { naked; version(X86) { /* Do something with the content of I and J. */ } version(X86_64) { /* Do something with the content of I and J. *? } } } void Bar() { MyStrunct heapStructA, heapStructB; // do some initialization. Foo(heapStructA, heapStructB); } Suppose I would like to pass first_arg and second_arg by register to `Foo`, what calling convention should I use? I'm having trouble identifying the correct calling convention I should be using for X86 and X86_64 in D. I've tried a couple using https://godbolt.org/ and DMD parameters '-g -m32', but I can't seem to find any that will pass by register. Is there one? Will it also work for LDC and GDC? 1) `asm {}` is supported by DMD and LDC, but not by GDC. 2) `extern(D)` reverses the args - `foo(a, b)` is actually `foo(b, a)` on a lower level. 3) The 32-bit x86 D calling convention (independent from OS) is specified here: https://dlang.org/spec/abi.html#function_calling_conventions All args are passed on the stack, except for the last one under certain circumstances, see point 38.12.3.3. 4) For x86_64, there are 2 (completely different) ABIs, Win64 and the System V one. Specs can be found online. In your case: void Foo(MyStrunct* first_arg, MyStrunct* second_arg) { asm { naked; } version (D_InlineAsm_X86) { // first_arg is on the stack, at [ESP+4] // second_arg is in EAX } else version (D_InlineAsm_X86_64) { version (Win64) { // first_arg is in RDX // second_arg is in RCX } else { // first_arg is in RSI // second_arg is in RDI } } }
Re: inline ASM function calling conventions.
On Sunday, 30 September 2018 at 11:53:17 UTC, Basile B. wrote: On Sunday, 30 September 2018 at 10:46:33 UTC, Sjoerd Nijboer wrote: [...] Hello, i think this should be here (https://dlang.org/spec/abi.html) because myself i never remember them correctly without playing a bit with a disassembler. After playing a bit: Without all the save/restore BS: module runnable; import std.stdio; alias write4Int = writeln!(int,int,int,int); struct MyStruct{int i;} extern(D) void foo(ref MyStruct s1, ref MyStruct s2, ref MyStruct s3, ref MyStruct s4) { asm { naked; mov RCX, MyStruct.i.offsetof[RCX]; mov RDX, MyStruct.i.offsetof[RDX]; mov RSI, MyStruct.i.offsetof[RSI]; mov RDI, MyStruct.i.offsetof[RDI]; callwrite4Int; ret; } } void main() { MyStruct s1 = MyStruct(1); MyStruct s2 = MyStruct(2); MyStruct s3 = MyStruct(3); MyStruct s4 = MyStruct(4); foo(s1, s2, s3, s4); }
Re: inline ASM function calling conventions.
On Sunday, 30 September 2018 at 10:46:33 UTC, Sjoerd Nijboer wrote: I'm kinda puzzled. I'm having trouble getting started with inline asm in D. Suppowse I have the following: void Foo(MyStrunct* first_arg, MyStrunct* second_arg) { asm { naked; version(X86) { /* Do something with the content of I and J. */ } version(X86_64) { /* Do something with the content of I and J. *? } } } void Bar() { MyStrunct heapStructA, heapStructB; // do some initialization. Foo(heapStructA, heapStructB); } Suppose I would like to pass first_arg and second_arg by register to `Foo`, what calling convention should I use? I'm having trouble identifying the correct calling convention I should be using for X86 and X86_64 in D. I've tried a couple using https://godbolt.org/ and DMD parameters '-g -m32', but I can't seem to find any that will pass by register. Is there one? Will it also work for LDC and GDC? Hello, i think this should be here (https://dlang.org/spec/abi.html) because myself i never remember them correctly without playing a bit with a disassembler. After playing a bit: Linux x86_64: extern(D) void Foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4) { asm { naked; // rcx -> s1 // rdx -> s2 // rsi -> s3 // rdi -> s4 ret; } } Linux x86 / Window x86: extern(D) void Foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4) { asm { naked; // ebx -> s1 // edx -> s2 // ecx -> s3 // eax -> s4 ret; } } Win64 has a different calling convention than Linux64, i cant remember the difference. Linux x86_64 example: module runnable; import std.stdio; alias writeInt = writeln!int; struct MyStruct{int i;} extern(D) void foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4) { asm { naked; mov RAX, RDI; // move s4 here since we call something... pushRDX;// save s2 pushRSI;// save s3 pushRAX;// save s4 mov RDI, MyStruct.i.offsetof[RCX]; callwriteInt; pop RAX;// restore... pop RSI; pop RDX; pushRSI; // save s3 pushRAX; // save s4 mov RDI, MyStruct.i.offsetof[RDX]; callwriteInt; pop RAX; // restore pop RSI; pushRAX; // save s4 mov RDI, MyStruct.i.offsetof[RSI]; callwriteInt; pop RAX; // restore mov RDI, MyStruct.i.offsetof[RAX]; callwriteInt; ret; } } void main() { MyStruct s1 = MyStruct(1); MyStruct s2 = MyStruct(2); MyStruct s3 = MyStruct(3); MyStruct s4 = MyStruct(4); foo(&s1, &s2, &s3, &s4); } here too : https://run.dlang.io/is/CWd4aO
Re: New With Struct and Getting Class Object Pointers
On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote: Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? Alex has mentioned Rebindable, which is the answer to your first question. To answer your second question, no class A {} A a: `a` is always a (possibly null) reference to a class instance. You can have pointers to class references (which is what `&a` gives you) but that has two indirections between the variable and the data, which if you want high perf is probably not what you are looking for.
inline ASM function calling conventions.
I'm kinda puzzled. I'm having trouble getting started with inline asm in D. Suppowse I have the following: void Foo(MyStrunct* first_arg, MyStrunct* second_arg) { asm { naked; version(X86) { /* Do something with the content of I and J. */ } version(X86_64) { /* Do something with the content of I and J. *? } } } void Bar() { MyStrunct heapStructA, heapStructB; // do some initialization. Foo(heapStructA, heapStructB); } Suppose I would like to pass first_arg and second_arg by register to `Foo`, what calling convention should I use? I'm having trouble identifying the correct calling convention I should be using for X86 and X86_64 in D. I've tried a couple using https://godbolt.org/ and DMD parameters '-g -m32', but I can't seem to find any that will pass by register. Is there one? Will it also work for LDC and GDC?
Re: New With Struct and Getting Class Object Pointers
On Sunday, 30 September 2018 at 10:28:25 UTC, Alex wrote: On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote: Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? I think, what you are facing here, is the different notion of const, as used from C++. The reasoning about it is described for example here: http://jmdavisprog.com/articles/why-const-sucks.html Jonathan is much better therein as I am. However, there are approaches to solve what you want to do. For example, there is a Rebindable around: https://dlang.org/library/std/typecons/rebindable.html ´´´ import std.stdio; import std.typecons; void main() { class Thing {int dummy; } class ThingSaver { /* A const(Thing) could not be changed in setThing(), but a Rebindable can be reassigned, keeping t const. */ Rebindable!(const Thing) t; void setThing(in Thing thing) { t = thing; // No pointers in use :) } const(Thing) getThing() const { return t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); //saver.t.dummy = 5; fails as expected. const(Thing) t2 = saver.getThing(); } ´´´ I hope, I got your idea right... That pretty much hits the nail on the head, and you're exactly right about where my understanding was coming from (C++). In fact, I'm moving a lot of code from C++ to D and finding equivalents for a lot of high-performance index classes, which end up using this kind of pattern. Now I need to take the time to grok this article!
Re: New With Struct and Getting Class Object Pointers
On Sunday, 30 September 2018 at 09:30:38 UTC, Vijay Nayar wrote: Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? For example: void main() { class Thing {} class ThingSaver { // A const(Thing) could not be changed in setThing(). const(Thing)* t; void setThing(in Thing thing) { t = thing; // ERROR converting to pointer type! } const(Thing) getThing() const { return *t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); const(Thing) t2 = saver.getThing(); } I think, what you are facing here, is the different notion of const, as used from C++. The reasoning about it is described for example here: http://jmdavisprog.com/articles/why-const-sucks.html Jonathan is much better therein as I am. However, there are approaches to solve what you want to do. For example, there is a Rebindable around: https://dlang.org/library/std/typecons/rebindable.html ´´´ import std.stdio; import std.typecons; void main() { class Thing {int dummy; } class ThingSaver { /* A const(Thing) could not be changed in setThing(), but a Rebindable can be reassigned, keeping t const. */ Rebindable!(const Thing) t; void setThing(in Thing thing) { t = thing; // No pointers in use :) } const(Thing) getThing() const { return t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); //saver.t.dummy = 5; fails as expected. const(Thing) t2 = saver.getThing(); } ´´´ I hope, I got your idea right...
Re: New With Struct and Getting Class Object Pointers
On Sunday, 30 September 2018 at 09:16:42 UTC, Nicholas Wilson wrote: On Sunday, 30 September 2018 at 07:29:00 UTC, Vijay Nayar wrote: Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object. &a = 0x7ffd0800acb8, a = 0x7fd6b05b, a.data=4 &a = 0x7ffd0800acd0, a = 0x7fd6b05b, a.data=4 The stack ^ the heap^data on the heap^ The address of the variable a on the stack has different values across function calls, its value (the reference to the class data) remains the same, as does the data itself. Is there a way to either have a constant reference to a class that can be set to a new value, or is there a way to convert the class variable to a class pointer? For example: void main() { class Thing {} class ThingSaver { // A const(Thing) could not be changed in setThing(). const(Thing)* t; void setThing(in Thing thing) { t = thing; // ERROR converting to pointer type! } const(Thing) getThing() const { return *t; } } Thing t1 = new Thing(); ThingSaver saver = new ThingSaver(); saver.setThing(t1); const(Thing) t2 = saver.getThing(); }
Re: New With Struct and Getting Class Object Pointers
On Sunday, 30 September 2018 at 07:29:00 UTC, Vijay Nayar wrote: I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); } Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object. How do you get a pointer to the underlying class object? Example of the problem: void main() { import std.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; writeln("&a = ", &a, ", a.data = ", a.data); } f(a); writeln("&a = ", &a, ", a.data = ", a.data); } // Output: &a = 7FFEA6BA3158, a.data = 4 // Addresses are different, from different class variables. &a = 7FFEA6BA3180, a.data = 4 // But the same underlying class object. Especially if I'm several levels down the call stack, how do I get a pointer to the underlying class object? the variable `a` is a pointer (well, actually reference) to the underlying data. void main() { import core.stdc.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; printf("&a = %p, a = %p, a.data=%d\n", &a, a,a.data); } f(a); printf("&a = %p, a = %p, a.data=%d\n", &a,a, a.data); } &a = 0x7ffd0800acb8, a = 0x7fd6b05b, a.data=4 &a = 0x7ffd0800acd0, a = 0x7fd6b05b, a.data=4 The stack ^ the heap^ data on the heap^ The address of the variable a on the stack has different values across function calls, its value (the reference to the class data) remains the same, as does the data itself.
Re: New With Struct and Getting Class Object Pointers
On 30/09/2018 8:29 PM, Vijay Nayar wrote: I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); } Yes. Uses a compiler hook to call into the GC, like with everything else.
New With Struct and Getting Class Object Pointers
I have two brief questions. Code that uses "new" to create struct objects appears to compile and run. Is this an actual language feature, to get structs on the heap? void main() { struct S {int data = 1;} S* s1 = new S(); S* s2 = s1; S s3 = *s1; // Still copies on assignment. s3.data = 2; assert(s1.data != s3.data); } Second question. const class variables may not be re-assigned, so if you need a variable that may be reassigned, but may never modify the underlying object, a const pointer can be useful. However, it seems that when gets the address of a class variable, you do not get the underlying address of the class object. How do you get a pointer to the underlying class object? Example of the problem: void main() { import std.stdio; class A { int data = 3; } A a = new A(); void f(A a) { a.data = 4; writeln("&a = ", &a, ", a.data = ", a.data); } f(a); writeln("&a = ", &a, ", a.data = ", a.data); } // Output: &a = 7FFEA6BA3158, a.data = 4 // Addresses are different, from different class variables. &a = 7FFEA6BA3180, a.data = 4 // But the same underlying class object. Especially if I'm several levels down the call stack, how do I get a pointer to the underlying class object?
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 06:56:41 UTC, bauss wrote: On Sunday, 30 September 2018 at 06:33:47 UTC, rikki cattermole wrote: null terminated, nothing really special. To elaborate on this. There is function that does it for you called toStringz() https://dlang.org/library/std/string/to_stringz.html Thanks for the reply. Let me check it.
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 06:33:47 UTC, rikki cattermole wrote: No. 2. Can we use D strings in win api functions ?, If not, please show me how to convert strings null terminated, nothing really special. Hi, Thanks for the reply. I somehow managed to display a messagebox with "const(wchar)*"
Re: Does the WInMain function is mandatory ?
On Sunday, 30 September 2018 at 06:33:47 UTC, rikki cattermole wrote: null terminated, nothing really special. To elaborate on this. There is function that does it for you called toStringz() https://dlang.org/library/std/string/to_stringz.html