Bug 19946 – In betterC filling an array with a non-zero value fails for types of size > 1 due to missing _memset16/_memset32/etc.

Status
NEW
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-06-07T08:59:48Z
Last change time
2024-12-13T19:03:49Z
Keywords
backend, betterC, pull
Assigned to
No Owner
Creator
Nathan S.
Depends on
21750
See also
https://issues.dlang.org/show_bug.cgi?id=19561
Moved to GitHub: dmd#19579 →

Comments

Comment #0 by n8sh.secondary — 2019-06-07T08:59:48Z
Example of code that doesn't work: ```d extern(C) void main() { alias int3 = int[3]; union U { ulong a = 1; uint[3] b; } // Can't set entire array slice to non-zero value unless type is size 1. { ushort[] a; a[] = 1; } //error: undefined reference to '_memset16' { int[] a; a[] = 1; } //error: undefined reference to '_memset32' { ulong[] a; a[] = 1; } //error: undefined reference to '_memset64' { float[] a; a[] = 1; } //error: undefined reference to '_memsetFloat' { double[] a; a[] = 1; } //error: undefined reference to '_memsetDouble' { cdouble[] a; a[] = cdouble.max; } //error: undefined reference to '_memset128' { creal[] a; a[] = creal.max; } //error: undefined reference to '_memset160' { int3[] a; int3 val = [1, 2, 3]; a[] = val; } //error: undefined reference to '_memsetn' { U[] a; a[] = U.init; } //error: undefined reference to '_memset128ii' // Can't give all members of static array non-zero initial value unless type is size 1. { ushort[4] a = 1; } //error: undefined reference to '_memset16' { int[4] a = 1; } //error: undefined reference to '_memset32' { ulong[4] a = 1; } //error: undefined reference to '_memset64' { float[4] a = 1; } //error: undefined reference to '_memsetFloat' { double[4] a = 1; } //error: undefined reference to '_memsetDouble' { cdouble[4] a = cdouble.max; } //error: undefined reference to '_memset128' { creal[4] a = creal.max; } //error: undefined reference to '_memset160' { U[4] a = U.init; } //error: undefined reference to '_memset128ii' // Static arrays of types with non-zero init also fail if not explicitly initialized. { wchar[4] a; } //error: undefined reference to '_memset16' { float[4] a; } //error: undefined reference to '_memsetFloat' { double[4] a; } //error: undefined reference to '_memsetDouble' { real[4] a; } //error: undefined reference to '_memset80' { cdouble[4] a; } //error: undefined reference to '_memset128' { creal[4] a; } //error: undefined reference to '_memset160' { U[4] a; } //error: undefined reference to '_memset128ii' // Static arrays of scalars wider than 8 bytes can't even be explicitly initialized as zero. { real[4] a = 0; } //error: undefined reference to '_memset80' { cdouble[4] a = 0+0i; } //error: undefined reference to '_memset128' { creal[4] a = 0+0i; } //error: undefined reference to '_memset160' { U[4] a = U(0); } //error: undefined reference to '_memset128ii' // Sometimes there is trouble even when individually specifying each element of the array. { int[4] a = [1, 1, 1, 1]; } //error: undefined reference to '_memset32' { int[4] a = [1, 2, 3, 4]; } //Works because compiler doesn't try to use memset-alike. // These work. { char[10] a; } //Works because ubyte.sizeof == 1 so it can use memset. { wchar[2] a = [0x1234, 0x5678]; a[] = 0; } //Works because the compiler realizes that it can use memset to zero the bits of a type regardless of its width. } ```
Comment #1 by snarwin+bugzilla — 2022-02-10T13:41:33Z
*** Issue 21879 has been marked as a duplicate of this issue. ***
Comment #2 by snarwin+bugzilla — 2022-02-10T13:42:20Z
*** Issue 21750 has been marked as a duplicate of this issue. ***
Comment #3 by dkorpel — 2022-06-02T18:04:37Z
These functions are defined in druntime's rt/memset, which is not linked with betterC. I'm not sure what the best fix is. The functions could be emitted in every translation unit that relies on them. Or, the code needs to be always inlined (though since some memset functions use inline asm, dmd cannot inline it currently).
Comment #4 by maxhaton — 2022-06-02T19:01:13Z
The fix is easy. I wrote the code but never got around to pushing it. It just needs to be a template in druntime. Hypothetically you could make it inline a loop but this might hurt LDC and GDC. arrayOp actually supports memset but making the array lowering use arrayOp would make it end up using itself. I also looked into using an arbitrary set memset in the backend but yuck.
Comment #5 by razvan.nitu1305 — 2022-06-03T06:57:08Z
(In reply to mhh from comment #4) > The fix is easy. I wrote the code but never got around to pushing it. > > It just needs to be a template in druntime. Hypothetically you could make it > inline a loop but this might hurt LDC and GDC. Besides making it a template, you also need to move the call insertion from e2ir to the frontend so that semantic analysis is performed on the instantiation. > > arrayOp actually supports memset but making the array lowering use arrayOp > would make it end up using itself. > > I also looked into using an arbitrary set memset in the backend but yuck. I think that long-term the best solution would be to lower the code in the frontend and, indeed, lower the hooks to templates.
Comment #6 by maxhaton — 2022-06-03T11:58:18Z
I am aware. I actually think we should have another dmd-only semantic pass just for this in dmd because the existing code is a complete mess. The case for array assign operations for example is just a branch in a hundreds of line visitor member.
Comment #7 by bugzilla — 2022-06-04T06:10:24Z
Razvan, your idea is the right approach. mhh, you're right, but this refactoring should be in a separate PR.
Comment #8 by dkorpel — 2022-06-08T10:24:27Z
*** Issue 20689 has been marked as a duplicate of this issue. ***
Comment #9 by dkorpel — 2022-06-08T10:25:47Z
*** Issue 17778 has been marked as a duplicate of this issue. ***
Comment #10 by dkorpel — 2022-06-08T10:30:14Z
(In reply to RazvanN from comment #5) > I think that long-term the best solution would be to lower the code in the > frontend and, indeed, lower the hooks to templates. I agree. My only reservation is that LDC and GDC seem to handle setting arrays in -betterC fine, but with a frontend lowering they might have a performance regression unless they start recognizing the new template hooks.
Comment #11 by dlang-bot — 2022-06-08T17:02:03Z
@dkorpel created dlang/druntime pull request #3837 "Issue 19946 - Add memset template function" mentioning this issue: - Issue 19946 - Add memset template function https://github.com/dlang/druntime/pull/3837
Comment #12 by alphaglosined — 2022-11-16T03:54:26Z
Another example that can trigger this (in -betterC): ```d extern(C) void main() { wchar[2] got; func(got); } void func(out wchar[2] v) { } ``` Why do these hooks even exist? They could be a simple rewrite to a foreach loop in the compiler and not depend on the runtime at all, let alone functions in rt.
Comment #13 by ibuclaw — 2022-12-27T17:01:49Z
This works with GDC and LDC. The problem is in the dmd backend.
Comment #14 by bugzilla — 2022-12-30T07:42:01Z
Comment #15 by alphaglosined — 2022-12-30T09:02:54Z
(In reply to Walter Bright from comment #14) > Start towards fixing this: https://github.com/dlang/dmd/pull/14761
Comment #16 by dlang-bot — 2022-12-30T19:32:36Z
@WalterBright created dlang/dmd pull request #14762 "fix Issue 19946 - In betterC filling an array with a non-zero value f…" fixing this issue: - fix Issue 19946 - In betterC filling an array with a non-zero value fails for types of size > 1 https://github.com/dlang/dmd/pull/14762
Comment #17 by bugzilla — 2022-12-30T19:38:10Z
This is not a regression, as it never worked.
Comment #18 by dlang-bot — 2023-01-02T09:07:23Z
@WalterBright created dlang/dmd pull request #14770 "handle byte, short, and int cases for bug 19946" mentioning this issue: - handle byte, short, and int cases for bug 19946 https://github.com/dlang/dmd/pull/14770
Comment #19 by dlang-bot — 2023-01-03T10:44:17Z
dlang/dmd pull request #14770 "handle byte, short, and int cases for bug 19946" was merged into master: - afb2a9bbc90edaf7063e073950adb1076ae56c7c by Walter Bright: handle byte, short, and int cases for bug 19946 https://github.com/dlang/dmd/pull/14770
Comment #20 by ryuukk.dev — 2023-01-03T13:38:22Z
Finally, thanks!!
Comment #21 by bugzilla — 2023-01-05T01:38:13Z
Comment #22 by dlang-bot — 2023-01-11T20:42:03Z
@WalterBright updated dlang/dmd pull request #14790 "fix Issue 23218 - cgxmm.d:1373 assert fail" mentioning this issue: - handle byte, short, and int cases for bug 19946 (#14770) https://github.com/dlang/dmd/pull/14790
Comment #23 by dlang-bot — 2023-01-14T03:45:21Z
@WalterBright updated dlang/dmd pull request #14805 "fix Issue 23614 - ImportC: __int128 not supported" mentioning this issue: - handle byte, short, and int cases for bug 19946 (#14770) https://github.com/dlang/dmd/pull/14805
Comment #24 by dlang-bot — 2023-02-24T11:07:22Z
@RazvanN7 updated dlang/dmd pull request #14884 "Fix Issue 23709 - Cannot use synchronized on shared class with -preview=nosharedaccess" mentioning this issue: - handle byte, short, and int cases for bug 19946 (#14770) https://github.com/dlang/dmd/pull/14884
Comment #25 by dlang-bot — 2023-02-24T11:54:34Z
@RazvanN7 updated dlang/dmd pull request #14909 "Fix Issue 23732 - Cannot create shared instance of class with -preview=nosharedaccess" mentioning this issue: - handle byte, short, and int cases for bug 19946 (#14770) https://github.com/dlang/dmd/pull/14909
Comment #26 by robert.schadek — 2024-12-13T19:03:49Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19579 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB