From 690a8d3a2a3f6243734a58458335509f83be6de6 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Tue, 12 Oct 2021 18:02:03 +0300 Subject: [PATCH 1/4] Make _d_arrayctor weakly pure Signed-off-by: Teodor Dutu --- src/core/internal/array/construction.d | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/core/internal/array/construction.d b/src/core/internal/array/construction.d index f1c4017747..b4346fcea8 100644 --- a/src/core/internal/array/construction.d +++ b/src/core/internal/array/construction.d @@ -21,9 +21,17 @@ import core.internal.traits : Unqual; * This function template was ported from a much older runtime hook that bypassed safety, * purity, and throwabilty checks. To prevent breaking existing code, this function template * is temporarily declared `@trusted` until the implementation can be brought up to modern D expectations. + * + * The third parameter is never used, but is necessary in order for the + * function be treated as weakly pure, instead of strongly pure. + * This is needed because constructions such as the one below can be ignored by + * the compiler if `_d_arrayctor` is believed to be pure, because purity would + * mean the call to `_d_arrayctor` has no effects (no side effects and the + * return value is ignored), despite it actually modifying the contents of `a`. + * const S[2] b; + * const S[2] a = b; // this would get lowered to _d_arrayctor(a, b) */ -Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @trusted - if (is(Unqual!T1 == Unqual!T2)) +Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* makeWeaklyPure = null) @trusted { pragma(inline, false); import core.internal.traits : hasElaborateCopyConstructor; @@ -45,7 +53,7 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste void[] vFrom = (cast(void*) from.ptr)[0..from.length]; void[] vTo = (cast(void*) toUn.to.ptr)[0..Tarr1.length]; - // Force `enforceRawArraysConformable` to be `pure` + // Force `enforceRawArraysConformable` to remain weakly `pure` void enforceRawArraysConformable(const char[] action, const size_t elementSize, const void[] a1, const void[] a2) @trusted { From 62671a8005792a2dfd3758725a9e0d30c6864575 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Tue, 12 Oct 2021 18:40:13 +0300 Subject: [PATCH 2/4] Add DDoc for makeWeaklyPure parameter Signed-off-by: Teodor Dutu --- src/core/internal/array/construction.d | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/internal/array/construction.d b/src/core/internal/array/construction.d index b4346fcea8..f3d74e4829 100644 --- a/src/core/internal/array/construction.d +++ b/src/core/internal/array/construction.d @@ -15,6 +15,8 @@ import core.internal.traits : Unqual; * Does array initialization (not assignment) from another array of the same element type. * Params: * from = what data the array should be initialized with + * makeWeaklyPure = unused; its purpose is to prevent the function from becoming + * pure and risk being optimised out * Returns: * The created and initialized array `to` * Bugs: From 51734313a1781fdb6974f921fabab09faef254b4 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Wed, 13 Oct 2021 16:59:03 +0300 Subject: [PATCH 3/4] Clarify makeWeaklyPure parameter description Signed-off-by: Teodor Dutu --- src/core/internal/array/construction.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/internal/array/construction.d b/src/core/internal/array/construction.d index f3d74e4829..324a1da08f 100644 --- a/src/core/internal/array/construction.d +++ b/src/core/internal/array/construction.d @@ -16,7 +16,7 @@ import core.internal.traits : Unqual; * Params: * from = what data the array should be initialized with * makeWeaklyPure = unused; its purpose is to prevent the function from becoming - * pure and risk being optimised out + * strongly pure and risk being optimised out * Returns: * The created and initialized array `to` * Bugs: From 18e07998f3bb0463df4b05f088db3b2e17894196 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Thu, 2 Dec 2021 19:40:50 +0200 Subject: [PATCH 4/4] _d_arrayctor: Roll back previous signature changes This undoes the changes brought by https://github.com/dlang/druntime/pull/3611 Signed-off-by: Teodor Dutu --- src/core/internal/array/construction.d | 37 +++++++++++--------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/core/internal/array/construction.d b/src/core/internal/array/construction.d index 324a1da08f..ae71f51312 100644 --- a/src/core/internal/array/construction.d +++ b/src/core/internal/array/construction.d @@ -14,6 +14,7 @@ import core.internal.traits : Unqual; /** * Does array initialization (not assignment) from another array of the same element type. * Params: + * to = what array to initialize * from = what data the array should be initialized with * makeWeaklyPure = unused; its purpose is to prevent the function from becoming * strongly pure and risk being optimised out @@ -42,18 +43,10 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma import core.stdc.stdint : uintptr_t; debug(PRINTF) import core.stdc.stdio : printf; - debug(PRINTF) printf("_d_arrayctor(from = %p,%d) size = %d\n", from.ptr, from.length, T1.sizeof); - - // Declare `to` inside a union so `__ArrayDtor(to)` isn't called in case - // `copyEmplace` throws. - union ToArr - { - Unqual!Tarr1 to; - } - ToArr toUn = void; + debug(PRINTF) printf("_d_arrayctor(from = %p,%d) size = %d\n", from.ptr, from.length, T.sizeof); void[] vFrom = (cast(void*) from.ptr)[0..from.length]; - void[] vTo = (cast(void*) toUn.to.ptr)[0..Tarr1.length]; + void[] vTo = (cast(void*) to.ptr)[0..to.length]; // Force `enforceRawArraysConformable` to remain weakly `pure` void enforceRawArraysConformable(const char[] action, const size_t elementSize, @@ -66,15 +59,15 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma (cast(Type)&enforceRawArraysConformableNogc)(action, elementSize, a1, a2, false); } - enforceRawArraysConformable("initialization", T1.sizeof, vFrom, vTo); + enforceRawArraysConformable("initialization", T.sizeof, vFrom, vTo); - static if (hasElaborateCopyConstructor!T1) + static if (hasElaborateCopyConstructor!T) { size_t i; try { - for (i = 0; i < toUn.to.length; i++) - copyEmplace(from[i], cast(T1) toUn.to[i]); + for (i = 0; i < to.length; i++) + copyEmplace(from[i], to[i]); } catch (Exception o) { @@ -82,7 +75,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma */ while (i--) { - auto elem = cast(Unqual!T1*) &toUn.to[i]; + auto elem = cast(Unqual!T*) &to[i]; destroy(*elem); } @@ -92,10 +85,10 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma else { // blit all elements at once - memcpy(cast(void*) toUn.to.ptr, from.ptr, toUn.to.length * T1.sizeof); + memcpy(cast(void*) to.ptr, from.ptr, to.length * T.sizeof); } - return cast(Tarr1) toUn; + return to; } // postblit @@ -110,7 +103,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma S[4] arr1; S[4] arr2 = [S(0), S(1), S(2), S(3)]; - arr1 = _d_arrayctor!(typeof(arr1))(arr2[]); + _d_arrayctor(arr1[], arr2[]); assert(counter == 4); assert(arr1 == arr2); @@ -133,7 +126,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma S[4] arr1; S[4] arr2 = [S(0), S(1), S(2), S(3)]; - arr1 = _d_arrayctor!(typeof(arr1))(arr2[]); + _d_arrayctor(arr1[], arr2[]); assert(counter == 4); assert(arr1 == arr2); @@ -159,7 +152,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma { Throw[4] a; Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)]; - a = _d_arrayctor!(typeof(a))(b[]); + _d_arrayctor(a[], b[]); } catch (Exception) { @@ -184,7 +177,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma { NoThrow[4] a; NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)]; - a = _d_arrayctor!(typeof(a))(b[]); + _d_arrayctor(a[], b[]); } catch (Exception) { @@ -290,7 +283,7 @@ void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted { Throw[4] a; Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)]; - a = _d_arrayctor!(typeof(a))(b[]); + _d_arrayctor(a[], b[]); } catch (Exception) {