Re: Hidden members of Class objects
On Thursday, 7 March 2024 at 00:28:17 UTC, Carl Sturtivant wrote: On Wednesday, 6 March 2024 at 23:45:00 UTC, H. S. Teoh wrote: In D, there's a pointer to the vtable and another pointer to a Monitor object (used for synchronized methods). There was talk about getting rid of the Monitor field years ago, but nothing has happened yet. Very interesting: is the monitor field ever touched by compiled D code at any point nowadays? Or is it just vestigial? It's (lazily initialized and) used by the `synchronized()` statement (§3 of https://dlang.org/spec/statement.html#synchronized-statement) and the mentioned `synchronized` class methods (https://dlang.org/spec/class.html#synchronized-methods).
Re: Why does disabling a struct's postblit increase its size in memory?
On Saturday, 2 March 2024 at 15:25:48 UTC, Per Nordlöw wrote: Why does disabling a struct's postblit increase its sizeof by one word? The following holds: ```d struct S { @disable this(this); int _; } struct T { int _; } static assert(S.sizeof == 16); static assert(T.sizeof == int.sizeof); ``` Not according to run.dlang.io, for all available DMD versions. Perhaps your tested `S` was nested in some function/aggregate and so had an implicit context pointer.
Re: Compile-time predicate for checking whether an aggregate field is static
On Saturday, 2 March 2024 at 15:22:03 UTC, Per Nordlöw wrote: How do I at compile-time check whether an aggregate field is static? https://dlang.org/phobos/std_traits.html#hasStaticMember perhaps.
Re: Inlined functions and their original bodies - bloat
The 'bloat' is usually gotten rid of by the linker if really unreferenced in the binary being linked. There's a little trick to make sure the function is *always* inlined, across modules too, allowing to suppress the then guaranteed unused function symbol - converting it to a function literal. See https://github.com/ldc-developers/ldc/issues/2968#issuecomment-1628615699.
Re: Getting the default value of a class member field
You could potentially skip running the `@constructValue` lambdas in the ctor via `if (__ctfe)`, if skipping this extra init is acceptable for CTFE instances.
Re: Getting the default value of a class member field
On Friday, 2 December 2022 at 04:14:37 UTC, kinke wrote: [...] Such an instance should be CTFE-constructible, and the valid instance would feature the expected value for the `validUntil` field. [...] Oh well, that time-sensitive example clearly isn't CTFE-able. :D - If that's the primary use case for these `@constructValue` UDAs, then yeah, this makes things more complicated.
Re: Getting the default value of a class member field
On Friday, 2 December 2022 at 00:24:44 UTC, WebFreak001 wrote: I want to use the static initializers (when used with an UDA) as default values inside my SQL database. See https://github.com/rorm-orm/dorm/blob/a86c7856e71bbc18cd50a7a6f701c325a4746518/source/dorm/declarative/conversion.d#L959 With my current design it's not really possible to move it out of compile time to runtime because the type description I create there gets serialized and output for use in another program (the migrator). Right now it's simply taking the compile time struct I generate and just dumping it without modification into a JSON serializer. [...] Okay, so what's blocking CTFE construction of these models? AFAICT, you have a templated base constructor in `Model`, which runs an optional `@constructValue!(() => Clock.currTime + 4.hours)` lambda UDA for all fields of the derived type. Can't you replace all of that with a default ctor in the derived type? ``` class MyModel : Model { int x = 123;// statically initialized SysTime validUntil; // dynamically initialized in ctor this() { validUntil = Clock.currTime + 4.hours; } } ``` Such an instance should be CTFE-constructible, and the valid instance would feature the expected value for the `validUntil` field. If you need to know about such dynamically generated fields (as e.g. here in this time-critical example), an option would be a `@dynamicallyInitialized` UDA. Then if you additionally need to be able to re-run these current `@constructValue` lambdas for an already constructed instance, you could probably go with creating a fresh new instance and copying over the fresh new field values.
Re: Getting the default value of a class member field
On Thursday, 1 December 2022 at 08:09:05 UTC, WebFreak001 wrote: I've got this class definition: ```d class X { this() { assert(false); } int x = 3; } ``` due to internal reasons the constructor would fail at compile time, so I put in an assert(false) here, and I can't add or change any methods in X. How do I get `3` if I have `X` and field name `"x"` at compile time? For structs `X.init.x` / `__traits(getMember, X.init, "x")` would work, however for classes it complains about null dereference. I saw there is __traits(initSymbol), however that one doesn't work at compile time. AFAIK, there is no way. Unlike a struct's init symbol, a class' one doesn't necessarily represent a valid instance state - it's just the raw payload before invoking a ctor (which constructs a valid instance), and the state 'dead' memory is reset to after finalizing an object instance (to prevent dead pointers keeping other GC refs alive). If the ctor worked at CTFE, one could use: ```d int get() { scope x = new X; return x.x; } enum bla = get(); ``` to get the `x` value of a *valid* instance, which might be different than the static initializer (if modified in the ctor). I guess the main question is why do you require the static initializers of these fields at compile-time. `__traits(initSymbol)` was added to aid in manual blitting at runtime.
Re: pragma(linkerDirective,_) removes double quotes, dmd ignores LIB
For LDC, you shouldn't need any double quotes, the compiler quotes the linker flag if it contains spaces.
Re: dub ldc2 static linking
For fully static linking on Linux, you'll need to move away from glibc to e.g. the musl C runtime, as used by the Alpine distro.
Re: "Error: no property `offsetof` for type `char*`"
On Friday, 19 August 2022 at 13:49:08 UTC, MyNameHere wrote: Thank you, that seems to have resolved the issue, though I wish these sorts of problems would stop cropping up, they are souring the experience with the language. Oh and `DevicePath()` is a convenience member returning a pointer to the 'dynamic array' (as the array decays to a pointer in C too), so no need to fiddle with `.offsetof` and computing the pointer manually.
Re: "Error: no property `offsetof` for type `char*`"
On Friday, 19 August 2022 at 14:22:04 UTC, Steven Schveighoffer wrote: On 8/19/22 9:49 AM, MyNameHere wrote: Thank you, that seems to have resolved the issue, though I wish these sorts of problems would stop cropping up, they are souring the experience with the language. Most likely that "member" is a macro in C. D doesn't have macros, so it uses properties. Nope, it's really a dynamically sized struct with a last `CHAR[1]` member: https://docs.microsoft.com/en-us/windows/win32/api/setupapi/ns-setupapi-sp_device_interface_detail_data_a Just like with C, these abominations need very special care, and regularly allocating on the stack or using as an aggregate field isn't possible.
Re: "Error: no property `offsetof` for type `char*`"
It's a method returning a `CHAR*` - `_DevicePath` is the actual member. I guess it's a dynamically sized struct, which cannot be mapped directly to D, hence this representation.
Re: How to call a function from a dll created with d ?
On Sunday, 3 July 2022 at 08:15:38 UTC, frame wrote: Are you sure? 100%, just try yourself. You import `testFunc` as normal import, the compiler ignores `pragma(lib)` - that's only for the linker which will ignore it too since the symbol is already in your executable. Why would the symbol be defined in the executable? `dimedll.d` isn't compiled into the executable. A static linked function should generate a very small lib-file and yours look too big to me. The code is using Phobos std.stdio.writeln templates, so the ~20 KB for both exe and DLL are to be expected and IMO absolutely acceptable. I don't know about LDC but with DMD I struggle with static linked DLLs because the library generated does not link to the DLL. To get right results, I need to pass the linker flag -`-L=/IMPLIB` (or `-L=/DLL` for 64bit) to generate a lib-file that is really linked to the DLL later. DMD's DLL support is waaay behind LDC's, especially once stuff gets more interesting than trivial examples.
Re: How to call a function from a dll created with d ?
With LDC, this is sufficient for this trivial example: ```d module dimedll; export void testFunc() { // export only needed when compiling with `-fvisibility=hidden` import std.stdio; writeln("This is from dll"); } ``` `ldc2 -shared dimedll.d` generates import lib + DLL. ```d import dimedll : testFunc; pragma(lib, "dimedll"); void main() { import std.stdio; writeln("Lets build our own ime"); testFunc(); } ``` `ldc2 -link-defaultlib-shared dime.d` generates the .exe and makes it share the druntime/Phobos DLLs with `dimedll.dll`. (More complex cases might need `-dllimport=all`). ``` C:\temp\dllTest>dime Lets build our own ime This is from dll C:\temp\dllTest>dir … 07/02/2022 03:54 PM 155 dime.d 07/02/2022 03:57 PM18,432 dime.exe 07/02/2022 03:57 PM19,679 dime.obj 07/02/2022 03:56 PM 162 dimedll.d 07/02/2022 03:57 PM20,480 dimedll.dll 07/02/2022 03:57 PM 7,534 dimedll.exp 07/02/2022 03:56 PM13,036 dimedll.lib 07/02/2022 03:57 PM21,233 dimedll.obj ``` On Posix, the only difference is that one would have to link `libdimedll.{so,dylib}` explicitly via `-L-ldimedll` instead of the `pragma(lib)`.
Re: D WebAssembly working differently than C++, Zig
The problem is the memset signature. You assume the length is the number of floats, while it's the number of *bytes* to be set to the specified value. https://en.cppreference.com/w/c/string/byte/memset
Re: Crosscompiling LDC's druntime for Android on Windows
On Monday, 21 February 2022 at 00:24:54 UTC, Fry wrote: I'm following the azure pipeline's commands for how it's being built here: https://github.com/ldc-developers/ldc/blob/master/.azure-pipelines/2-posix-build_cross_android.yml#L64 You can check the CI logs for the expanded cmdlines, e.g., from https://dev.azure.com/ldc-developers/ldc/_build/results?buildId=3281=logs=0dd91bf4-5270-5f6c-2450-fbc036057a53=0dd91bf4-5270-5f6c-2450-fbc036057a53=c2436f57-6a96-592e-95de-a459be0e607b: ldc-build-runtime --ninja -j 2 '--dFlags=-fvisibility=hidden;-mtriple=aarch64--linux-android;-gcc=/home/vsts/work/1/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang' '--targetSystem=Android;Linux;UNIX' --ldcSrcDir=/home/vsts/work/1/s ANDROID_ABI=arm64-v8a ANDROID_NATIVE_API_LEVEL=21 ANDROID_STL=c++_static CMAKE_CROSSCOMPILING=True LDC_INSTALL_LLVM_RUNTIME_LIBS_OS=android LDC_INSTALL_LLVM_RUNTIME_LIBS_ARCH=aarch64-android CMAKE_TOOLCHAIN_FILE=/home/vsts/work/1/android-ndk-r21e/build/cmake/android.toolchain.cmake
Re: Does anyone build for Android? Tons of link errors..
On Friday, 18 February 2022 at 16:28:56 UTC, Fry wrote: Does anyone know why the bfd linker is needed and why the gold linker doesn't work for the emulated TLS? It's required for LDC's custom TLS emulation for Android, see 1st point in https://wiki.dlang.org/Build_D_for_Android#Directions_for_future_work. lld supports custom linker scripts AFAIK, so that should get it to work as well (putting the two sections adjacent to each other). There's a runtime check making sure the executable has been linked as expected.
Re: Does anyone build for Android? Tons of link errors..
On Wednesday, 16 February 2022 at 20:40:02 UTC, Fry wrote: A lot of unresolved references to just CPU_COUNT. The confusing part is that it has undefined referenced to parts of in `core`, which I am linking the druntime as well. If you're linking manually, make sure that `-ldruntime-ldc` comes *after* `-lphobos2-ldc`, and that your druntime lib has been compiled for the appropriate arch. CPU_COUNT is a druntime symbol too.
Re: Cross Compile to Linux from Windows using LDC?
On Thursday, 10 February 2022 at 16:52:32 UTC, H. S. Teoh wrote: If I understand it right, you ought to be able to do the same thing on Windows [...] Not quite; cross-compiling to Windows has been made especially simple and is a special case. When cross-compiling from Windows to Linux, this applies: https://wiki.dlang.org/Cross-compiling_with_LDC#Non-Apple_POSIX_targets - a working C cross-compiler setup is required for linking, incl. glibc.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
An example: a.d: ``` import core.stdc.stdio; void foo()() { version (Oops) printf(" foo - oops\n"); else printf(" foo\n"); } void doA() { printf("doA:\n"); foo!(); } ``` b.d: ``` import core.stdc.stdio; import a; void main() { printf("main:\n"); foo!(); doA(); } ``` ```bash $ dmd -c a.d -version=Oops $ dmd -c b.d $ dmd a.o b.o -of=ab $ ./ab main: foo - oops doA: foo - oops $ dmd b.o a.o -of=ba $ ./ba main: foo doA: foo ``` Each object file contains a foo!() instantiation (in a.o, the Oops version). No inlining, so the linker takes one of the weak definitions, and we end up with a consistent behavior for both calls - but the picked version is determined by the order of the object files. Now if the calls are inlined, the behavior might not be consistent anymore. So separate compilations with different compiler flags can cause observable differences.
Re: ldc2 failed with exit code -1073741819.
On Tuesday, 18 January 2022 at 16:25:45 UTC, Anonymouse wrote: What can I *reasonably* do here? Do I *have* to compile LDC from source, to get debug symbols? How else can I reduce it when it doesn't say what goes wrong? [-1073741819 == 0xc005 => access violation] Some options: 1. This might be 'caught' by an existing assertion. You can use a CI build (https://github.com/ldc-developers/ldc/releases/tag/CI) with enabled assertions to check. 2. In case the segfault does NOT happen in the frontend, enabling verbose codegen via `-vv` can be of great help to see what the glue layer was doing right before the crash (at the end of the potentially huge log). My manual reductions usually start there for glue layer crashes.
Re: How to deploy single exe application (?)
On Monday, 29 November 2021 at 03:59:11 UTC, kinke wrote: `ldc\curl.exp` Typo, should have been `lib\curl.exp`.
Re: How to deploy single exe application (?)
On Sunday, 28 November 2021 at 16:08:20 UTC, Willem wrote: Is it possible to distribute an .exe file without the required libcurl DLL? LDC ships with a static curl library - `lib\curl_a.lib`. IIRC, you'll also need to export the curl symbols from the .exe for std.net.curl consumption, by adding `ldc\curl.exp` in the compiler command-line too.
Re: AVX for math code ... avx instructions later disappearing ?
On Sunday, 26 September 2021 at 18:08:46 UTC, james.p.leblanc wrote: or even moving the array declarations to before the dot product function, and the avx instructions will disappear! That's because the `@fastmath` UDA applies to the next declaration only, which is the `x` array in your 2nd example (where it obviously has no effect). Either use `@fastmath:` with the colon to apply it to the entire scope, or use `-ffast-math` in the LDC cmdline. Similarly, when moving the function to another module and you don't include that module in the cmdline, it's only imported and not compiled and won't show up in the resulting assembly. Wrt. stack alignment, there aren't any issues with LDC AFAIK (not limited to 16 or whatever like DMD).
Re: LDC 1.28.0-beta1
Argh, wrong forum section, proper (identical) post: https://forum.dlang.org/thread/hcwukzoamezbpzrbk...@forum.dlang.org
LDC 1.28.0-beta1
Glad to announce the first beta for LDC 1.28 - some highlights: * Based on D 2.098.0-beta.2+ (today's stable). * Dynamic casts across binary boundaries (DLLs etc.) now work. * Windows: `-dllimport=defaultLibsOnly` doesn't require `-linkonce-templates` anymore. Full release log and downloads: https://github.com/ldc-developers/ldc/releases/tag/v1.28.0-beta1 Please help test, and thanks to all contributors & sponsors!
Re: Cannot catch exception in debug mode
On Thursday, 12 August 2021 at 02:03:39 UTC, Adam D Ruppe wrote: On Thursday, 12 August 2021 at 01:53:12 UTC, frame wrote: Is this a known DMD bug or feature? Huh that is weird, it works correctly in gdc but i can reproduce in dmd and ldc. And removing the debug keyword makes it work. Certainly smells like a regression bug to me. Yep, apparently a v2.094 frontend regression (the `catch(Exception)` in the debug block is removed from the AST): https://run.dlang.io/is/nPRiT7 @frame: Please file an issue.
Re: align dynamic array (for avx friendliness) hints? / possible??
On Tuesday, 3 August 2021 at 12:33:56 UTC, james.p.leblanc wrote: Concise question: = I would like to use dynamic arrays, not for their dynamic sizing properties per se' (slicing, appending, etc). But, more for their memory protection and efficiencies (for example,using foreach). However, I must have the start of my array at an avx friendly 32 byte alignment. Is this easily acheivable? Background: === I am interfacing with fftw. If I use the fftw_malloc, then I am forced to either: 1) copy to/from the allocated arrays to/from my "standard" dlang dynamic arrays (loss of efficiency). or ... 2) use standard array/pointer mechanisms everywhere(loss of memory safely). My thinking is that I could forego the use of the fftw_malloc, and simply hand fftw functions my (properly aligned) pointer of my dlang dynamic array. All thoughts, comments, hints, greatly appreciated! James AFAIK, the GC only guarantees an alignment of 16. But you can turn any memory allocation into a slice, simply via ``` size_t length = ...; T* myPtr = cast(T*) fftw_malloc(length * T.sizeof); // or aligned_alloc, posix_memalign etc. T[] mySlice = myPtr[0 .. length]; foreach (ref e; mySlice) ... // free! ```
Re: Why are class methods not allowed to call cons/destructors?
On Saturday, 31 July 2021 at 13:59:46 UTC, Tejas wrote: On Saturday, 31 July 2021 at 13:57:40 UTC, kinke wrote: This is possible via: ``` __dtor(); super.__dtor(); ``` WHOO YEAH!!! THANK YOU SO MUCH :D Heh you're welcome. Note that you'll probably want `__xdtor()`, which also destructs fields with dtor (no base fields - `super.__xdtor()` for the immediate base class etc.).
Re: Why are class methods not allowed to call cons/destructors?
This is possible via: ``` __dtor(); super.__dtor(); ```
Re: LLVM asm with constraints, and 2 operands
On Monday, 19 July 2021 at 17:20:21 UTC, kinke wrote: Compiling with `-O -mtriple=i686-linux-gnu -mcpu=i686` (=> no SSE2 by default) shows that the inlined version inside `wrapper()` is the mega slow one, so the extra instructions aren't applied transitively unfortunately. Erm sorry should have looked more closely - it's not inlined, and the call seems extremely expensive too, with state pushing and popping going on, apparently to account for the different targets. Brrr, to be avoided at all costs for such tiny functions. :)
Re: LLVM asm with constraints, and 2 operands
On Monday, 19 July 2021 at 16:44:35 UTC, Guillaume Piolat wrote: On Monday, 19 July 2021 at 10:49:56 UTC, kinke wrote: This workaround is actually missing the clobber constraint for `%2`, which might be problematic after inlining. An unrelated other issue with asm/__asm is that it doesn't follow consistent VEX encoding compared to normal compiler output. sometimes you might want: paddq x, y at other times: vpaddq x, y, z but rarely both in the same program. So this can easily nullify any gain obtained with VEX transition costs (if they are still a thing). You know that asm is to be avoided whenever possible, but unfortunately, AFAIK intel-intrinsics doesn't fit the usual 'don't worry, simply compile all your code with an appropriate -mattr/-mcpu option' recommendation, as it employs runtime detection of available CPU instructions. I've just tried another option, but that doesn't play nice with inlining: ``` import core.simd; import ldc.attributes; @target("sse2") // use SSE2 for this function int4 _mm_add_int4(int4 a, int4 b) { return a + b; // perfect: paddd %xmm1, %xmm0 } int4 wrapper(int4 a, int4 b) { return _mm_add_int4(a, b); } ``` Compiling with `-O -mtriple=i686-linux-gnu -mcpu=i686` (=> no SSE2 by default) shows that the inlined version inside `wrapper()` is the mega slow one, so the extra instructions aren't applied transitively unfortunately.
Re: LLVM asm with constraints, and 2 operands
On Monday, 19 July 2021 at 11:39:02 UTC, Basile B. wrote: And what about the `extern(C)` issue ? Does it make sense to be used when the parameters are int4 ? The original inline asm was buggy and only 'worked' by accident (not using the 2nd input operand at all...) with extern(D) reversed parameters. At least for Posix x64, the C calling convention is well-defined for vectors and equivalent to extern(D) (except for the latter's parameter reversal). Windows and 32-bit x86 are different; for Windows, extern(D) pays off, as LDC's ABI is similar to the MSVC++ __vectorcall calling convention (passing vectors in SIMD registers).
Re: LLVM asm with constraints, and 2 operands
On Monday, 19 July 2021 at 11:16:49 UTC, Tejas wrote: On Monday, 19 July 2021 at 10:49:56 UTC, kinke wrote: On[snip] Is LDC still compatible with GDC/GCC inline asm? I remember Johan saying they will break compatibilty in the near future... I'm not aware of any of that; who'd be 'they'? GCC breaking their syntax is IMO unimaginable. LDC supporting it (to some extent) is pretty recent, was introduced with v1.21.
Re: LLVM asm with constraints, and 2 operands
On Monday, 19 July 2021 at 10:21:58 UTC, kinke wrote: What works reliably is a manual mov: ``` int4 _mm_add_int4(int4 a, int4 b) { int4 r; asm { "paddd %1, %2; movdqa %2, %0" : "=x" (r) : "x" (a), "x" (b); } return r; } ``` This workaround is actually missing the clobber constraint for `%2`, which might be problematic after inlining. You can also specify the registers explicitly like so (here exploiting ABI knowledge about `a` being passed in XMM1, and `b` in XMM0 for extern(D)): ``` int4 _mm_add_int4(int4 a, int4 b) { asm { "paddd %1, %0" : "=xmm0" (b) : "xmm1" (a), "xmm0" (b); } return b; } ``` => ``` paddd xmm0, xmm1 ret ``` But this might likely tamper with LLVM register allocation optimizations after inlining...
Re: LLVM asm with constraints, and 2 operands
On Sunday, 18 July 2021 at 16:32:46 UTC, Basile B. wrote: - **=x** says "returns in whatever is has to" - **x** (1) is the constraint for input `a`, which is passed as operand **$0** - **x** (2) is the constraint for input `b`, which is passed as operand **$1** $0 is actually the output operand, $1 is `a`, and $2 is `b`. The official docs are here, but IMO not very user-friendly: https://llvm.org/docs/LangRef.html#inline-assembler-expressions I recommend using GDC/GCC inline asm instead, where you'll find more examples. For the given paddd example, I'd have gone with ``` int4 _mm_add_int4(int4 a, int4 b) { asm { "paddd %1, %0" : "=*x" (a) : "x" (b); } // the above is equivalent to: // __asm!void("paddd $1, $0","=*x,x", , b); return a; } ``` but the produced asm is rubbish (apparently an LLVM issue): ``` movaps %xmm1, -24(%rsp) paddd %xmm0, %xmm0 // WTF? movaps %xmm0, -24(%rsp) retq ``` What works reliably is a manual mov: ``` int4 _mm_add_int4(int4 a, int4 b) { int4 r; asm { "paddd %1, %2; movdqa %2, %0" : "=x" (r) : "x" (a), "x" (b); } return r; } ``` => ``` paddd %xmm1, %xmm0 movdqa %xmm0, %xmm0 // useless but cannot be optimized away retq ``` Note: inline asm syntax and resulting asm in AT syntax, *not* Intel syntax.
Re: Are D classes proper reference types?
On Sunday, 27 June 2021 at 12:00:41 UTC, Ola Fosheim Grøstad wrote: On Sunday, 27 June 2021 at 10:11:44 UTC, kinke wrote: Right, but what does all supported C++ runtimes mean? I thought LDC was tied to clang, which I guess means two runtimes? If C++ doesn't use arbitrary negative offsets, then D could use those? LDC isn't tied to clang at all, we just use the same backend. - It's libstdc++ and libc++ in the POSIX world (most likely including MinGW), and MSVC++ for 'native' Windows. Another difficulty is that TypeInfo_Class instances are generated by the compiler, and not in the frontend either, meaning that DMD, GDC and LDC would all need to be adapted.
Re: Are D classes proper reference types?
On Sunday, 27 June 2021 at 09:46:45 UTC, Ola Fosheim Grøstad wrote: On Sunday, 27 June 2021 at 08:41:27 UTC, kinke wrote: Getting rid of the monitor field was discussed multiple times. You don't have to get rid of it, just implicitly declare it for classes that use monitors? I don't think it has to be at a specific offset? It's not about classes using monitors themselves, it's about people potentially using `synchronized (obj)` for some arbitrary class reference `obj`. Embedding it in the instance directly prevents having to use a hashtable or similar. But I'm certainly not fond of that field as it's a rare use case. The other major and not so trivial difference is that extern(C++) classes have no TypeInfo pointer (in the first vtable slot for extern(D) classes), which also means that dynamic casts don't work, neither in D nor in C++ (for the latter, only for instances instiantiated on the D side). [AFAIK, most C++ implementations put the - of course totally incompatible - *C++* TypeInfo into vtable slot -1.] But D could just extend C++ typeinfo? Sure, 'just' :D - as it 'just' takes someone to implement it (for all supported C++ runtimes). It's always the same problem, lots of talk and blabla in the forum, but hardly any real action coming out of it.
Re: Are D classes proper reference types?
On Sunday, 27 June 2021 at 07:54:38 UTC, Ola Fosheim Grøstad wrote: That is all good, but it will lead to `extern(C++) class` replacing D classes. So why not unify right away? Why wait for the inevitable? The assumption that all D code and all classes therein are or need to be designed for C++ interop is daring. The DMD frontend uses extern(C++) classes almost exclusively, but that's just for LDC and GDC. Getting rid of the monitor field was discussed multiple times. The other major and not so trivial difference is that extern(C++) classes have no TypeInfo pointer (in the first vtable slot for extern(D) classes), which also means that dynamic casts don't work, neither in D nor in C++ (for the latter, only for instances instiantiated on the D side). [AFAIK, most C++ implementations put the - of course totally incompatible - *C++* TypeInfo into vtable slot -1.]
Re: Are D classes proper reference types?
On Saturday, 26 June 2021 at 20:03:01 UTC, kinke wrote: With C++, you can today, an `extern(C++) class C` is equivalent to and mangled as C++ `C*`. You can't pass it directly to some `unique_ptr` or `shared_ptr` of course; an according D wrapper reflecting the C++ implementation (library-dependent) would be needed anyway for correct mangling. It'd be implemented as a templated D struct, similar to how `std::vector` works today for the MSVC runtime: https://github.com/dlang/druntime/blob/master/src/core/stdcpp/vector.d Oh, I've just seen that unique_ptr is already implemented in https://github.com/dlang/druntime/blob/master/src/core/stdcpp/memory.d, and according to the tests, working for the MSVC++ runtime, see https://github.com/dlang/druntime/pull/2723/files.
Re: Are D classes proper reference types?
On Saturday, 26 June 2021 at 13:49:25 UTC, Ola Fosheim Grøstad wrote: Is it possible to inherit from a C++ class and get a D subclass, and is it possible to inherit from a D class and get a C++ class? Sure thing, with `extern(C++) class` of course. But the best solution is to get to a place where you can hand D-objects to other languages with ease without doing a runtime conversion from one layout to another. With C++, you can today, an `extern(C++) class C` is equivalent to and mangled as C++ `C*`. You can't pass it directly to some `unique_ptr` or `shared_ptr` of course; an according D wrapper reflecting the C++ implementation (library-dependent) would be needed anyway for correct mangling. It'd be implemented as a templated D struct, similar to how `std::vector` works today for the MSVC runtime: https://github.com/dlang/druntime/blob/master/src/core/stdcpp/vector.d
Re: Are D classes proper reference types?
On Saturday, 26 June 2021 at 07:00:37 UTC, Ola Fosheim Grøstad wrote: Weak pointers aren't in the language, so I don't see why they would matter here. I thought you were after replacing GC-allocated class instances by a simple RC scheme. One goal could be to make a class compatible with C++ or Swift on request. Both support weak pointers. You could have multiple ref-count layout schemes as long as they all are on negative offsets. Just don't mix class hierarchies. So you could mix a D class hierarchy, C++ class-hiearchy and Swift class-hierarchy in the same codebase? I'm pretty sure I haven't seen a weak pointer in C++ yet. I don't look at C++ much anymore, but I suspect they are even a lot rarer than shared_ptr. Wrt. mixed class hierarchies, being able to inherit from and instantiate C++ classes in D is of some priority and mostly works today. (Let's not get into discussing multiple inheritance here, it's hardly a show-stopper for most use cases.) Is Swift a thing outside the Apple universe (I admittedly despise ;))? It's surely much better than their Objective-C crap, but still... So for rare use cases like shared_ptr/weak pointer interop, a library solution (just like they are in C++) is IMO enough.
Re: Are D classes proper reference types?
On Friday, 25 June 2021 at 17:05:41 UTC, Ola Fosheim Grøstad wrote: Yes, if you don't want to support weak pointers. I think you need two counters if you want to enable the usage of weak pointers. I cannot imagine how weak pointers would work without an ugly extra indirection layer. If we're on the same page, we're talking about embedding the reference counter *directly* in the class instance, and the class ref still pointing directly to the instance. Weak pointers aren't in the language, so I don't see why they would matter here. I thought you were after replacing GC-allocated class instances by a simple RC scheme. One reason to put it at a negative offset is that it makes it possible to make it fully compatible with shared_ptr. In modern C++ code I've been looking at so far, shared_ptr was used very rarely (and unique_ptr everywhere). AFAIK, the main reason being poor performance due to the extra indirection of shared_ptr. So replacing every D class ref by a shared_ptr-analogon for interop reasons would seem very backwards to me.
Re: Are D classes proper reference types?
Wrt. manual non-heap allocations (stack/data segment/emplace etc.), you could e.g. reserve the most significant bit of the counter to denote such instances and prevent them from being free'd (and possibly finalization/destruction too; this would need some more thought I suppose).
Re: Are D classes proper reference types?
On Friday, 25 June 2021 at 06:09:17 UTC, Ola Fosheim Grøstad wrote: On Thursday, 24 June 2021 at 07:28:56 UTC, kinke wrote: Yes, class *refs* are always pointers. *scope* classes are deprecated (I don't think I've ever seen one); with `scope c = new Object`, you can have the compiler allocate a class *instance* on the stack for you, but `c` is still a *ref*. But the user code cannot depend on it being stack allocated? So I could replace the Object reference with a reference counting pointer and put the counter at a negative offset? Well AFAIK it's mandated by the language, so an RC scheme replacing such allocations by heap ones seems like a definite step backwards - it's a useful pattern, and as Stefan pointed out, definitely in use. You could still stack-allocate but accommodate for the counter prefix in the compiler. `emplace` doesn't allocate, you have to pass the memory explicitly. This is more of a problem. I was thinking about arrays that provide an emplace method, then one could replace emplace with heap allocation. I guess it isn't really possible to make `emplace` with custom memory work gracefully with reference counting with ref count at negative offset. It's certainly possible as it's a library thing; some existing code may assume the returned reference to point to the beginning of the passed memory though (where there'd be your counter). What you'd definitely need to adjust is `__traits(classInstanceSize)`, accomodating for the extra counter prefix. There's very likely existing code out there which doesn't use druntime's emplace[Initializer], but does it manually. A class *instance* can also live in the static data segment (`static immutable myStaticObject = new Object;`); But it isn't required to? It certainly wouldn't work with reference counting if it is stored in read only memory... Not required to AFAIK, but if it's not statically allocated, you'd need to allocate it at runtime via some module or CRT ctor. It's probably easier to have the compiler put it into static but writable memory, so that you can mess with the counter. --- All in all, I think a more interesting/feasible approach would be abusing the monitor field of extern(D) classes for the reference counter. It's the 2nd field (of pointer size) of each class instance, directly after the vptr (pointer to vtable). I think all monitor access goes through a druntime call, so you could hook into there, disallowing any regular monitor access, and put this (AFAIK, seldomly used) monitor field to some good use.
Re: Are D classes proper reference types?
On Thursday, 24 June 2021 at 12:31:08 UTC, Stefan Koch wrote: On Thursday, 24 June 2021 at 07:28:56 UTC, kinke wrote: On Thursday, 24 June 2021 at 06:50:44 UTC, Ola Fosheim Grøstad wrote: [...] (I don't think I've ever seen one); with `scope c = new Object`, you can have the compiler allocate a class *instance* on the stack for you, but `c` is still a *ref*. The dmd frontend uses them all the time to avoid allocation overhead for Visitors. I was talking about not having seen a `scope class C { ... }`, *not* the `scope` storage class as in the example.
Re: Are D classes proper reference types?
On Thursday, 24 June 2021 at 06:50:44 UTC, Ola Fosheim Grøstad wrote: [...] Yes, class *refs* are always pointers. *scope* classes are deprecated (I don't think I've ever seen one); with `scope c = new Object`, you can have the compiler allocate a class *instance* on the stack for you, but `c` is still a *ref*. `emplace` doesn't allocate, you have to pass the memory explicitly. A class *instance* can also live in the static data segment (`static immutable myStaticObject = new Object;`); `extern(C++)` class instances can also live on the C++ heap/stack etc. etc.
Re: LNK2019 error in the C++ interface
On Thursday, 10 June 2021 at 13:19:34 UTC, dokutoku wrote: The reason seems to be that WCHAR should be mangled with wcha_t, but it is mangled with chat16_t. Confirmed: https://issues.dlang.org/show_bug.cgi?id=22014 Wrt. `tagRECT`, this should come in handy (for a druntime fix): https://dlang.org/changelog/2.097.0.html#pragma-mangle-aggregate
Re: Shift operator, unexpected result
On Wednesday, 9 June 2021 at 19:13:10 UTC, JG wrote: I found the following behaviour, as part of a more complicated algorithm, unexpected. The program: import std; void main() { int n = 64; writeln(123uL>>n); } produces: 123 I would expect 0. What is the rationale for this behaviour or is it a bug? This is undefined behavior as in other languages, see §3 in https://dlang.org/spec/expression.html#shift_expressions.
Re: How to compile Phobos with other D code to create a shared library?
On Monday, 31 May 2021 at 19:21:52 UTC, data pulverizer wrote: ldc2 jbasic.d -O3 -link-defaultlib-shared --betterC --boundscheck=off -nogc -shared -of=jbasic.so The problem is almost certainly `-betterC`, which disables linking against Phobos and druntime.
Re: isPOD is broken?
A class *reference* is always a POD. Only structs can be non-PODs.
Re: dmd -> ldmd2: /usr/bin/ld.gold: error: .o: multiple definition of 'bool ldc.attributes...
On Sunday, 7 March 2021 at 11:34:08 UTC, kdevel wrote: ./dmd -i -I=tillyscop:tillyscop/msgpack-d/src -O -g -of=localscop.o -c tillyscop/scop.d tillyscop/scopserializer.d and ./dmd -i -of=pointless.o -g -c pointless/package.d "dmd" is a symlink to /opt/ldc2/bin/ldmd2 Ah, try using `-i=-ldc` instead of `-i` alone to manually exclude the ldc.* modules from being included.
Re: Using YMM registers causes an undefined label error
On Saturday, 6 March 2021 at 12:29:07 UTC, kinke wrote: There are other slight breakages of that 'spec', e.g., LDC's extern(D) ABI is very similar to Microsoft's __vectorcall (so that e.g. vectors are passed in registers). [Windows only, to prevent any more confusion.]
Re: Using YMM registers causes an undefined label error
On Saturday, 6 March 2021 at 12:15:43 UTC, Mike Parker wrote: On Saturday, 6 March 2021 at 11:57:13 UTC, Imperatorn wrote: What... Is this really how it's supposed to be? Makes no sense to not use any of the existing conventions. extern(C) and extern(D) are both documented to be the same as the platform's C calling convention everywhere except x86 windows: https://dlang.org/spec/abi.html#function_calling_conventions There have been times when differences were noted (I recall a particularly bad one related to passing structs by value on 64-bit linux) and there may be more. When they are, they should be reported in Bugzilla. The main difference is that the params are reversed for extern(D), at least with DMD and LDC, not with GDC. And that can't be easily changed because of all the naked DMD-style inline asm code (GDC doesn't support that, so no problem for GDC). This comes up regularly here in this forum whenever people experiment with DMD-style asm. There are other slight breakages of that 'spec', e.g., LDC's extern(D) ABI is very similar to Microsoft's __vectorcall (so that e.g. vectors are passed in registers).
Re: Using YMM registers causes an undefined label error
On Friday, 5 March 2021 at 12:57:43 UTC, z wrote: XMM registers work, but as soon as they are changed into YMM DMD outputs "bad type/size of operands %s" and LDC outputs an "label YMM0 is undefined" error. Are they not supported? To illutrate : https://run.dlang.io/is/IqDHlK LDC's support for DMD-style inline asm is limited; GDC-style inline asm is the preferred way (e.g., not restricted to x86[_64] and no need to worry about calling convention details). Your example can be reduced to a trivial: import core.simd; ubyte32 complement32(ubyte32 a, ubyte32 b) { return a ^ b; } which yields the following asm with `ldc2 -mattr=avx -O` (see https://d.godbolt.org/z/ex7YE7): _D7example12complement32FNhG32hQgZQj: vxorps ymm0, ymm1, ymm0 ret
Re: dub support for Mac M1?
On Thursday, 4 March 2021 at 22:30:17 UTC, tastyminerals wrote: I got a company MacBook with M1 chip and gradually migrate all the stuff from Linux machine. I got precompiled ldc binary installed without any problem now is the time for dub since I have couple of D projects I use at work and all of them use dub. I can only see the dub-v1.23.0-osx-x86_64.tar.gz package so it should at least run via Rosetta. The official prebuilt LDC package comes with prebuilt dub, dustmite, ddemangle and rdmd, just like any other package.
Re: Class instance alignment
On Monday, 22 February 2021 at 02:23:27 UTC, Steven Schveighoffer wrote: Hm... but does TypeInfo detail alignment? Apparently not for TypeInfo_Class; .talign() returns the alignment of a class *ref*, i.e., pointer size. TypeInfo_Struct.talign() does return the struct alignment though and could be used to select a larger bin size.
Re: Class instance alignment
On Saturday, 20 February 2021 at 18:43:53 UTC, Steven Schveighoffer wrote: Last I checked*, the GC uses pools of 16-byte, 32-byte, 64-byte, etc blocks. That has changed [to reduce wastage]; the new bin sizes are here and include sizes like 176 (11*16): https://github.com/dlang/druntime/blob/728f1d9c3b7a37eba4d59ee2637fb924053cba6d/src/core/internal/gc/impl/conservative/gc.d#L1166 (not sure about stack alignment for scope instances) This works with LDC at least. E.g., this: class C { align(64) int[2] data; } void foo() { scope c = new C(); } allocates 72 bytes aligned at a 64-bytes stack boundary. 72 bytes? :) Yes - vptr, monitor, then 48 padding bytes (for 64-bit target...), then 8 `data` bytes with .offsetof of 64. [And classes don't need tail padding, as you can't allocate arrays of class *instances* directly in the language.] Structs are generally better suited for alignment purposes, but the same GC limitations apply when allocating them on the heap.
Re: Class instance alignment
On Friday, 19 February 2021 at 23:53:55 UTC, tsbockman wrote: How can I get the alignment of a class instance? I know how to get the size: __traits(classInstanceSize, T) But, there doesn't appear to be any equivalent trait for the alignment. There's https://github.com/dlang/druntime/blob/728f1d9c3b7a37eba4d59ee2637fb924053cba6d/src/core/internal/traits.d#L261. But AFAIK, the GC only guarantees an alignment of 16 and doesn't respect any overaligned members or alignment spec for the class.
Re: Struct delegate access corruption
On Wednesday, 17 February 2021 at 20:44:46 UTC, tsbockman wrote: On Wednesday, 17 February 2021 at 20:18:53 UTC, Paul Backus wrote: On Wednesday, 17 February 2021 at 19:42:00 UTC, tsbockman wrote: A copy constructor and opAssign can be used to update pointers that are relative to : https://dlang.org/spec/struct.html#struct-copy-constructor Unfortunately this is not enough, because the compiler is free to implicitly move struct instances in memory any time it wants to. See the bug report below for more details: https://issues.dlang.org/show_bug.cgi?id=17448 Until D gets move constructors, structs with interior pointers should be avoided. That bug is about postblits, this(this), not copy constructors: this(ref typeof(this)). Copy constructors were added to the language specifically to fix those sort of problems. Nope, Paul is right, the copy ctors don't solve anything in this regard. Simplest example I could come up with: https://run.dlang.io/is/TgxyU3
Re: Wrapping C++ class with virtual destructor
On Wednesday, 17 February 2021 at 22:53:05 UTC, Gregor Mückl wrote: Hi! How do I wrap an existing C++ class with a virtual destructor in D? Take, for example, this C++ class: class Base { public: virtual ~Base(); virtual void foo() = 0; } What does the equivalent extern(C++) declaration in D look like? I don't care about calling the destructor. My only concern is matching the vtable. Changing the C++ code is not an option in my case. extern(C++) class Base { ~this(); abstract void foo(); }
Re: Real simple unresolved external symbols question...
On Thursday, 11 February 2021 at 00:18:23 UTC, H. S. Teoh wrote: On Wed, Feb 10, 2021 at 11:35:27PM +, WhatMeWorry via Digitalmars-d-learn wrote: [...] Okay, thanks. Then why does the README.md at https://github.com/dlang/druntime say "Runtime is typically linked together with Phobos in a release such that the compiler only has to link to a single library to provide the user with the runtime and the standard library." Probably outdated information. Somebody should submit a PR for it. ;-) It basically says there's no separate libdruntime with DMD, it's included in libphobos2 (unlike LDC). So 'runtime' in the context of the druntime repo is 'druntime', not 'C runtime and other platform libs' libphobos/druntime depend on.
Re: Real simple unresolved external symbols question...
On Tuesday, 9 February 2021 at 19:37:17 UTC, WhatMeWorry wrote: I'm trying to create a super simple dynamic library consisting of two files: file2.d -- extern(D): double addEight(double d) { return (d + 8.0); } fileB.d -- extern(D) { string concatSuffix(string s) { return (s ~ ".ext"); } } dmd -m64 -c file2.d dmd -m64 -c fileB.d creates file2.obj and fileB.obj files link.exe /DLL /NOENTRY file2.obj fileB.obj msvcrt.lib If you go the easy route and use LDC, everything works: ldc2 -shared file1.d file2.d => file1.dll Or, if you really prefer separate compile + link: ldc2 -c file1.d ldc2 -c file2.d ldc2 -shared file1.obj file2.obj Use `-v` to see what the actual link.exe cmdline is, and notice the MSVC and Windows libs that are implicitly added. - IIRC, DMD only embeds these system libs into the object file containing main/DllMain (and you have none), whereas LDC adds them to the linker cmdline.
Re: emplace doesn't forward aeguments
On Saturday, 30 January 2021 at 17:29:15 UTC, vitamin wrote: On Thursday, 28 January 2021 at 23:18:21 UTC, kinke wrote: On Thursday, 28 January 2021 at 21:15:49 UTC, vitamin wrote: Is there reason why std.conv.emplace doesn't forward arguments to __ctor? Yeah, a bug in the emplace() version for classes, some missing `forward!args` in there (it works when emplacing a struct with identical ctor). E.g. https://github.com/dlang/druntime/blob/e2e304e1709b0b30ab65471a98023131f0e7620c/src/core/lifetime.d#L124-L128 if you want to fix it (std.conv.emplace is now an alias for core.lifetime.emplace in Phobos master). thanks; It's already fixed: https://github.com/dlang/druntime/pull/3352
Re: emplace doesn't forward aeguments
On Thursday, 28 January 2021 at 21:15:49 UTC, vitamin wrote: Is there reason why std.conv.emplace doesn't forward arguments to __ctor? Yeah, a bug in the emplace() version for classes, some missing `forward!args` in there (it works when emplacing a struct with identical ctor). E.g. https://github.com/dlang/druntime/blob/e2e304e1709b0b30ab65471a98023131f0e7620c/src/core/lifetime.d#L124-L128 if you want to fix it (std.conv.emplace is now an alias for core.lifetime.emplace in Phobos master).
Re: 64-bit compilation in Wine
On Tuesday, 29 December 2020 at 21:13:59 UTC, Raikia wrote: That certainly helped, but when running the program on a fresh Windows install, I still get the error "The program can't start because vcruntime140.dll is missing from your computer". In my (limited) experience, I think its because it is using msvcrt (which is dynamically linked) instead of libcmt (which is static). The static MS libs cannot be redistributed by 3rd parties thanks to their license, that's why LDC and DMD only come with MinGW-based import libraries depending on an installed MSVC++ runtime. [DMD works with (default) -m32 because that uses Walter's DigitalMars C runtime.]
Re: d++: Error: Could not execute `dmd c.o .\foo.d -offoo.exe`:
On Saturday, 21 November 2020 at 17:25:46 UTC, Jack wrote: I got the error: Error: Could not execute `dmd c.o .\foo.d -offoo.exe`: Error: unrecognized file extension o dmd version: DMD32 D Compiler v2.094.1-dirty gcc version: gcc version 6.3.0 (MinGW.org GCC-6.3.0-1) DMD expects .obj for Windows. So you'll probably have to use the MS compiler or clang to emit an MSVC-compatible object file, and then use either -m32mscoff or -m64 for DMD.
Re: rt/object.d
On Thursday, 29 October 2020 at 16:02:34 UTC, Ola Fosheim Grøstad wrote: I meant the internals like vtable/typeinfo. https://dlang.org/spec/abi.html#classes
Re: Passing pointer to extern(C++) templated function
On Wednesday, 14 October 2020 at 00:25:56 UTC, Jamie wrote: Happy to file a bug, but if it was a bug in the mangler wouldn't both C++ and D get the same result? Assuming D uses the same mangler for the extern(C++) stuff. Bug in the D frontend implementation of Itanium C++ mangling. https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d
Re: Passing pointer to extern(C++) templated function
On Tuesday, 13 October 2020 at 09:23:48 UTC, Jamie wrote: It appears that func3 and func4 take on different types depending on other variables being present? Is this expected? Nope, it's a bug in the Itanium C++ mangler, please file a bug. MSVC++ mangling seems fine, after fixing the D declarations to void func3(T)(T* b, const(T)* a); void func4(T)(const(T)* a, T* b); [A D `const T*` is equivalent to C++ `const T* const`; this matters for MSVC mangling...].
Re: Link Time Optimization Bitcode File Format
On Tuesday, 6 October 2020 at 16:46:28 UTC, Severin Teona wrote: Also, when I try to link the druntime with the application I want to write on the microcontroller, there are some link errors due to the file format. This happens when you link manually, not through LDC. When running LDC with `-flto=full -O -v ...`, you'll see that it invokes gcc with extra flags, something like -Wl,-plugin,/dlang/ldc-1.23.0/lib/LLVMgold-ldc.so -Wl,-plugin-opt=mcpu=x86-64 -Wl,-plugin-opt=O3 -Wl,-plugin-opt=-function-sections -Wl,-plugin-opt=-data-sections so that the linker gets to know how to deal with bitcode objects via the LLVM plugin. See http://johanengelen.github.io/ldc/2016/11/10/Link-Time-Optimization-LDC.html for more infos about LTO.
Re: Trying to create a trivial 64 bit D Lang DLL on a Windows 10 machine and cant get past linking.
On Thursday, 1 October 2020 at 20:03:19 UTC, WhatMeWorry wrote: Yes, but shouldn't the /NOENTRY option take care of that. Say, I just want to make a DLL of simple functions. Your little example has 2 problems, the first being an incompatible extern(D) ex/import (mydll.myAddSeven vs. user.myAddSeven) and the second being an incomplete/wrong linker cmdline. When changing the myAddSeven declarations to extern(C++) (another option being a mydll.di header for the import), it works with dmd -m64 -shared -L/NOENTRY mydll.d dmd -m64 user.d mydll.lib For more details, see also https://wiki.dlang.org/Win32_DLLs_in_D.
Re: How to implement fastcall ?
On Wednesday, 23 September 2020 at 19:50:13 UTC, Denis Feklushkin wrote: On Monday, 21 September 2020 at 11:14:06 UTC, Виталий Фадеев wrote: How to implement fastcall ? ( stdcall is calling convention for pass function arguments via registers ) Hypothesis: it is possible what LLVM + Link Time Optimization does by this way. ~All modern ABIs use registers; __fastcall was one of the special 32-bit x86 ABIs AFAIK (using up to 2 GP registers) and isn't supported directly. The D ABI for 32-bit x86 uses one GP register (and is somewhat similar to __thiscall for member functions).
Re: Trouble with Android and arsd.jni
On Thursday, 10 September 2020 at 13:14:00 UTC, burt wrote: However, the app is still crashing when I load it, and there appears to be an issue in Runtime.initialize(), which is called from JNI_OnLoad(), which is defined in arsd.jni. The debugger tells me that it was calling `getStaticTLSRange`, which calls `safeAssert` in the `__foreachbody`, which fails and eventually aborts. That safeAssert would print a useful message, but I guess you can obtain the msg/reason via debugging as well. - This is most likely due to *not* using the required bfd linker (which is used by default when linking via LDC and otherwise selectable via `-linker=bfd`). If you're linking manually via clang, try `-fuse-ld=bfd`.
Re: Trouble with Android and arsd.jni
On Thursday, 10 September 2020 at 11:16:55 UTC, burt wrote: However, I am getting linker errors, telling me that _tlsend, _tlsstart and __bss_end__ are missing. Perhaps you happen to use some stale artifacts? These magic symbols aren't used anymore in druntime since LDC v1.21, and not defined by the compiler anymore. You also don't need the dummy main() anymore. The object file containing the undefined references should shed some light on what's still referencing them.
Re: GC.LDC2 on Android
On Tuesday, 8 September 2020 at 12:47:11 UTC, Danny Arends wrote: How can I figure out which linker is used ? When performing a dub build, it just mentions that ldc2 is used for linking You can add -v as dub 'linker' flag, that will make LDC show the actual cmdline. LDC v1.23 defaults to `-linker=bfd` for Android targets though. And now I actually remember that you should get a startup error in case the linker sections arrangement is a problem, so it's most likely not the linker. The good feedback mentioned earlier, where the GC was apparently no problem: https://github.com/ldc-developers/ldc/issues/3461#issuecomment-648599814
Re: GC.LDC2 on Android
On Tuesday, 8 September 2020 at 11:17:45 UTC, Danny Arends wrote: Does anyone have any experience with using D on android, and using the garbage collector ??? I've never run anything on Android myself, but I've gotten good feedback on AArch64 at least. Make sure to use a recent LDC, and especially to use the bfd linker, not gold or lld, as mentioned in various places.
Re: Building LDC runtime for a microcontroller
On Monday, 7 September 2020 at 15:23:28 UTC, Severin Teona wrote: CMake Error at /snap/cmake/549/share/cmake-3.18/Modules/CMakeTestCCompiler.cmake:66 (message): This is apparently a non-LDC specific issue, a default CMake C compiler sanity check fails. When looking at that file, you'll see that this test should be skipped when providing CMAKE_C_COMPILER_WORKS=TRUE in the CMake cmdline, as provided in one of the exemplary cmdlines on the Wiki page (just append it to the ldc-build-runtime cmdline).
Re: How to define delegate what returns ref?
On Friday, 28 August 2020 at 11:46:15 UTC, Oleg B wrote: How to do this more clearly? alias Dg = ref int delegate(); Dg foo;
Re: BetterC + WASM Update
On Wednesday, 19 August 2020 at 21:24:23 UTC, Mike Brown wrote: I have done some tests, and it appears that classes are supported (LDC 1.22.0)? extern(C++) classes are supported by -betterC. With LDC, D classes are supported to some extent too since v1.11, but this requires a custom object.d (custom Object base class).
Re: LDC cross-module-inlining
On Monday, 10 August 2020 at 11:11:57 UTC, Per Nordlöw wrote: Are the official LDC-releases builtin with or without LTO? Most of them are, but not sure why that matters here (the gain is almost negligible and mainly interesting for the C++ parts - as all D files are compiled to a single object file anyway). On Monday, 10 August 2020 at 05:54:14 UTC, Daniel Kozak wrote: I am not sure but last time I checked ldc does not do cross module inlinig by default, Right, it's still experimental and has issues. and LTO only help if your ldc(druntime+phobos) are built with enabled LTO That's only true if (mostly non-templated) functions in druntime/Phobos are to be cross-module inlined, just like any other library. In that case, you can simply use `-flto= -defaultlib=phobos2-ldc-lto,druntime-ldc-lto` with LDC builds shipping with LTO druntime/Phobos and don't have to recompile druntime/Phobos manually anymore.
Re: __vector(ubyte[32]) misalignment
On Sunday, 9 August 2020 at 01:03:51 UTC, Bruce Carneal wrote: Is sub .alignof alignment expected here? IOW, do I have to manually manage memory if I want alignments above 16? IIRC, yes when using the GC, as that only guarantees 16-bytes alignment. Static arrays on the stack should be aligned just fine with LDC.
Re: Forcing inline functions (again) - groan
On Wednesday, 15 July 2020 at 13:38:34 UTC, Cecil Ward wrote: I recently noticed pragma(inline, true) which looks extremely useful. A couple of questions : 1. Is this cross-compiler compatible? Works for LDC and DMD, not sure about GDC, but if it doesn't support it, it's definitely on Iain's list. 2. Can I declare a function in one module and have it _inlined_ in another module at the call site? For LDC, this works in all cases (i.e., also if compiling multiple object files in a single cmdline) since v1.22. While you cannot force LLVM to actually inline, I haven't come across a case yet where it doesn't.
Re: Choosing a non-default linker for dmd (via dub)
On Wednesday, 15 July 2020 at 11:38:47 UTC, Jacob Carlborg wrote: There's an environment variable "CC" that can be used to select which C compiler is used. Is there any equivalence for selecting the linker, "LD" perhaps? You normally just add -fuse-ld=gold to the C compiler cmdline, e.g., via -Xcc=-fuse-ld=gold in the DMD cmdline.
Re: BetterC Bug? Intended Behavior? Asking Here As Unsure
On Monday, 6 July 2020 at 22:02:37 UTC, Kayomn wrote: On Monday, 6 July 2020 at 21:09:57 UTC, kinke wrote: Similar case here; the 'varargs' end up in a GC-allocated array. I've recently changed `scope` slice params, so that array literal arguments are allocated on the caller's stack instead; so adding `scope` for these variadics *should* probably do the same: void tester(Test test, scope Test[] tests...); This doesn't seem to be the case as the issue persists in the same manner. https://run.dlang.io/is/LcaKeu I meant 'should' as in 'should be fixed to do the same', as this works with -betterC: struct Test { ~this() {} } void tester(Test test, scope Test[] tests) { } extern(C) void main() { tester(Test(), [Test()]); }
Re: BetterC Bug? Intended Behavior? Asking Here As Unsure
On Monday, 6 July 2020 at 20:25:11 UTC, Kayomn wrote: Though, admittedly I'm kind of used to seeing this error message since it appears any time you try and do something that relies on type info in betterC, intentionally or not. A notable example is forgetting to supply an arrange length when declaring a stack array, or it'll try to create a runtime-allocated array. Similar case here; the 'varargs' end up in a GC-allocated array. I've recently changed `scope` slice params, so that array literal arguments are allocated on the caller's stack instead; so adding `scope` for these variadics *should* probably do the same: void tester(Test test, scope Test[] tests...);
Re: Catching OS Exceptions in Windows using LDC
On Saturday, 4 July 2020 at 12:59:03 UTC, Adam D. Ruppe wrote: For whatever reason, dmd 64 bit and ldc decided to do their own thing instead of following the Windows standard and thus have no interop with OS exceptions. For LDC, we don't do 'our own thing', but use MSVC++ EH, which allows to catch MSVC++ exceptions in D, and with some work, D exceptions in C++.
Re: Generating struct .init at run time?
On Thursday, 2 July 2020 at 16:51:52 UTC, kinke wrote: `= void` for members doesn't work and, I dare say, not work anytime soon if ever. I've quickly checked; `= void` for members has initialize-with-zeros semantics too, so with LDC, it's equivalent to `= 0` but applicable to user-defined types as well. For DMD, `= void` for non-default-zero-initialized members can be used for the same effect. If all members are effectively zero-initialized, the init symbol isn't emitted, and the compiler initializes the whole struct with zeros. With `= 0`, DMD still emits the init symbol into the object file, but doesn't use it (at least not for stack allocations). TLDR: Seems like initializing (all non-default-zero-initialized) members with `= void` is the portable solution to elide the init symbols *and* have the compiler initialize the whole struct with zeros, so a manual memset isn't required.
Re: Generating struct .init at run time?
On Thursday, 2 July 2020 at 15:20:23 UTC, Ali Çehreli wrote: According to its date, it was written when I was working for Weka. Apparently, ldc took care of it for them after all. If so, then without them posting any issue beforehand or giving any feedback afterwards. > For recent LDC versions, the 'solution' is to (statically) initialize > the array with zeros, as fully zero-initialized structs don't feature > any explicit .init symbols anymore. What about floating point and char types? Their .init values are not all zeros in D spec. (I don't think this matters in my case but still.) That's why all you have to do, in order not to have recent LDC emit the struct's init symbol, is to initialize these members manually with zeros: struct S { double[elementCount] a = 0; } void foo() { S s; } // compiler does a memset `= void` for members doesn't work and, I dare say, not work anytime soon if ever.
Re: Generating struct .init at run time?
On Thursday, 2 July 2020 at 07:51:29 UTC, Ali Çehreli wrote: Of course, the solution is to define members with '= void' Since when? https://issues.dlang.org/show_bug.cgi?id=11331 and your https://issues.dlang.org/show_bug.cgi?id=16956 are still open. For recent LDC versions, the 'solution' is to (statically) initialize the array with zeros, as fully zero-initialized structs don't feature any explicit .init symbols anymore. enum elementCount = 1024 * 1024; struct S { double[elementCount] a = void; // <-- HERE } void main() { S s; assert(typeid(S).initializer.length == double.sizeof * elementCount); assert(typeid(S).initializer.ptr is null); } Now the program binary is 800M shorter. So you're saying you have a *stack* that can deal with an 800M struct (assuming you used a different `elementCount` for the actual tests)?! Even 8 MB should be too large without extra compiler/linker options, as that's the default stack size on Linux IIRC (on Windows, 2 MB IIRC). I don't think a struct should ever be that large, as it can probably only live on the heap anyway and only passed around by refs. I'd probably use a thin struct instead, containing and managing a `double[]` member (or `double[elementCount]*`).
Re: Linking D with C structs
On Monday, 29 June 2020 at 06:29:38 UTC, Anthony wrote: What does "__initZ" refer to? Does this refer to automatic initialization like "this()"? Almost, it's the static initializer for that struct, which is omitted because you apparently don't compile/link the module containing the struct declaration. Initialize the char array with zeros (= 0) to make the struct fully zero-initialized, preventing the need for that symbol. chars in D are initialized with 0xFF, unlike byte and ubyte.
Re: Garbage collection
On Saturday, 27 June 2020 at 15:27:34 UTC, Stanislav Blinov wrote: On Saturday, 27 June 2020 at 14:12:09 UTC, kinke wrote: Note that I explicitly clear the `str` slice before GC.collect(), so that the stack shouldn't contain any refs to the fat string anymore. Hrm... What happens if you call collect() twice? Nothing changes, even when collecting 5 times at the end of each iteration. In the filed testcase, I've extracted the stack ref to a dedicated function, so that there really shouldn't be any refs on the stack (this is unoptimized code after all...).
Re: Garbage collection
=> https://issues.dlang.org/show_bug.cgi?id=20983
Re: Garbage collection
On Saturday, 27 June 2020 at 10:08:15 UTC, James Gray wrote: have run into a memory leak Something seems really off indeed. I've run this on Win64 with DMD (2.092) and LDC (1.22), without any extra cmdline options: - import core.memory; import core.stdc.stdio; import std.range; import std.format; auto f(R)(R r) { return format("%s", r); } int toMB(ulong size) { return cast(int) (size / 1048576.0 + 0.5); } void printGCStats() { const stats = GC.stats; const used = toMB(stats.usedSize); const free = toMB(stats.freeSize); const total = toMB(stats.usedSize + stats.freeSize); printf(" GC stats: %dM used, %dM free, %dM total\n", used, free, total); } void main() { printGCStats(); while (true) { puts("Starting"); string str = f(iota(100_000_000)); printf(" string size: %dM\n", toMB(str.length)); str = null; GC.collect(); printGCStats(); } } - Output with DMD (no change with the precise GC via `--DRT-gcopt=gc:precise`): - GC stats: 0M used, 1M free, 1M total Starting string size: 943M GC stats: 1168M used, 1139M free, 2306M total Starting string size: 943M GC stats: 1168M used, 2456M free, 3623M total Starting string size: 943M GC stats: 1168M used, 2456M free, 3623M total Starting string size: 943M GC stats: 1168M used, 2456M free, 3623M total Starting string size: 943M GC stats: 1168M used, 2456M free, 3623M total - With LDC: - GC stats: 0M used, 1M free, 1M total Starting string size: 943M GC stats: 1168M used, 1139M free, 2306M total Starting string size: 943M GC stats: 2335M used, 1288M free, 3623M total Starting string size: 943M GC stats: 2335M used, 2605M free, 4940M total Starting string size: 943M GC stats: 2335M used, 2605M free, 4940M total Starting string size: 943M GC stats: 2335M used, 2605M free, 4940M total - Note that I explicitly clear the `str` slice before GC.collect(), so that the stack shouldn't contain any refs to the fat string anymore.
Re: figure out where a particular template function is located
On Wednesday, 24 June 2020 at 21:05:12 UTC, Steven Schveighoffer wrote: I have a hard time believing that there's no way to do this! This would IMO be the job of the IDE. E.g., Visual D might be able to jump to the template declaration.
Re: figure out where a particular template function is located
On Wednesday, 24 June 2020 at 20:28:24 UTC, Steven Schveighoffer wrote: Is there a way to figure this out from the call? Another option would be running LDC with -vv for verbose codegen (be warned, lots and lots ouf output); we have fully qualified names in there.
Re: real.mant_dig on windows?
On Tuesday, 23 June 2020 at 02:56:36 UTC, 9il wrote: Should it always be 53? or it can be 64, when? Thank you For LDC, it's 53 (and .sizeof == 8) for MSVC targets, but 64 (x87) for MinGW, reflecting the accompanying C runtime's `long double`. [And IIRC, MS disallows any x87 usage in kernel code.] For DMD, it's always 64, it only has x87 reals.
Re: called copy constructor in foreach with ref on Range
On Monday, 22 June 2020 at 20:51:37 UTC, Jonathan M Davis wrote: [...] That's why I put the struct in parantheses. Moving a class ref makes hardly any sense, but I've also never written a *class* to represent a range. Moving is the no-brainer solution for transferring ownership of struct ranges and invalidating the original instance.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
If you are referring to the next line, not the next n lines, that's a simple `continue;` statement.