Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 16c836a

Browse files
authored
Merge pull request #3583 from teodutu/nogc-aray-utils
Add @nogc variants for array utils functions
2 parents d624421 + da07528 commit 16c836a

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

src/core/internal/array/construction.d

+13-8
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,25 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
2828
import core.lifetime : copyEmplace;
2929
import core.stdc.string : memcpy;
3030
import core.stdc.stdint : uintptr_t;
31-
debug(PRINTF) import core.stdc.stdio;
31+
debug(PRINTF) import core.stdc.stdio : printf;
3232

3333
debug(PRINTF) printf("_d_arrayctor(to = %p,%d, from = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, T.tsize);
3434

35-
// Rewrite `enforceRawArraysConformable` manually to allow @nogc.
36-
// Use more austere errors because @nogc doesn't allow string concatenation.
3735
void[] vFrom = (cast(void*)from.ptr)[0..from.length];
3836
void[] vTo = (cast(void*)to.ptr)[0..to.length];
39-
assert(vFrom.length == vTo.length, "Array lengths don't match");
4037

41-
const ptrTo = cast(uintptr_t)vTo.ptr;
42-
const ptrFrom = cast(uintptr_t)vFrom.ptr;
43-
const d = ptrTo > ptrFrom ? ptrTo - ptrFrom : ptrFrom - ptrTo;
44-
assert(d >= vFrom.length * T.sizeof, "Overlapping arrays");
38+
// Force `enforceRawArraysConformable` to be `pure`
39+
void enforceRawArraysConformable(const char[] action, const size_t elementSize,
40+
const void[] a1, const void[] a2) @trusted
41+
{
42+
import core.internal.util.array : enforceRawArraysConformableNogc;
43+
44+
alias Type = void function(const char[] action, const size_t elementSize,
45+
const void[] a1, const void[] a2, in bool allowOverlap = false) @nogc pure nothrow;
46+
(cast(Type)&enforceRawArraysConformableNogc)(action, elementSize, a1, a2, false);
47+
}
48+
49+
enforceRawArraysConformable("initialization", T.sizeof, vFrom, vTo);
4550

4651
static if (hasElaborateCopyConstructor!T)
4752
{

src/core/internal/util/array.d

+49
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ import core.internal.string;
1313
import core.stdc.stdint;
1414

1515

16+
// TLS storage shared for all error messages.
17+
private align(2 * size_t.sizeof) char[256] _store;
18+
19+
private char[] errorMessage(Args...)(scope const(char*) format,
20+
const char[] action, Args args) @trusted
21+
{
22+
import core.stdc.stdio : snprintf;
23+
snprintf(&_store[0], _store.sizeof, format, &action[0], args);
24+
return _store;
25+
}
26+
1627
@safe /* pure dmd @@@BUG11461@@@ */ nothrow:
1728

1829
void enforceTypedArraysConformable(T)(const char[] action,
@@ -65,6 +76,44 @@ private void _enforceNoOverlap(const char[] action,
6576
assert(0, msg);
6677
}
6778

79+
void enforceTypedArraysConformableNogc(T)(const char[] action,
80+
const T[] a1, const T[] a2, const bool allowOverlap = false)
81+
{
82+
_enforceSameLengthNogc(action, a1.length, a2.length);
83+
if (!allowOverlap)
84+
_enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
85+
}
86+
87+
void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize,
88+
const void[] a1, const void[] a2, const bool allowOverlap = false)
89+
{
90+
_enforceSameLengthNogc(action, a1.length, a2.length);
91+
if (!allowOverlap)
92+
_enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length);
93+
}
94+
95+
private void _enforceNoOverlapNogc(const ref char[] action,
96+
uintptr_t ptr1, uintptr_t ptr2, const size_t bytes)
97+
{
98+
const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1;
99+
if (d >= bytes)
100+
return;
101+
const overlappedBytes = bytes - d;
102+
103+
assert(0, errorMessage("Overlapping arrays in %s: %zu byte(s) overlap of %zu",
104+
action, overlappedBytes, bytes));
105+
}
106+
107+
private void _enforceSameLengthNogc(const ref char[] action,
108+
const size_t length1, const size_t length2)
109+
{
110+
if (length1 == length2)
111+
return;
112+
113+
assert(0, errorMessage("Array lengths don't match for %s: %zu != %zu",
114+
action, length1, length2));
115+
}
116+
68117
private uintptr_t arrayToPtr(const void[] array) @trusted
69118
{
70119
// Ok because the user will never dereference the pointer

0 commit comments

Comments
 (0)