mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-25 08:45:32 +08:00
D front-end changes: - `scope' semantics are now enforced in `@safe' code on pointers to stack memory, but only as deprecation warnings. - Overriding virtual functions are now marked with the `override' and `final' in the generated headers of `-fdump-c++-spec='. - `-fpreview=fiximmmutableconv` has been added that disallows implicitly converting a return value with indirections to immutable if it determines the result must be unique. D runtime changes: - Posix (excluding Darwin): Switch default GC signals from SIGUSR1/2 to SIGRTMIN/SIGRTMIN+1 Phobos changes: - Import latest bug fixes to mainline. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 4d07f22f2 * d-lang.cc (d_handle_option): Handle OPT_fpreview_fiximmutableconv. * lang.opt (fpreview=fiximmutableconv): New option. * runtime.def (ARRAYAPPENDT): Remove. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime f89da313. * src/MERGE: Merge upstream phobos d46814c86. Signed-off-by: Iain Buclaw <ibuclaw@gdcproject.org>
191 lines
5.5 KiB
D
191 lines
5.5 KiB
D
/**
|
|
* Implementation of array assignment support routines.
|
|
*
|
|
*
|
|
* Copyright: Copyright Digital Mars 2010 - 2016.
|
|
* License: Distributed under the
|
|
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
|
|
* Authors: Walter Bright, Kenji Hara
|
|
* Source: $(DRUNTIMESRC rt/_arrayassign.d)
|
|
*/
|
|
|
|
module rt.arrayassign;
|
|
|
|
private
|
|
{
|
|
import core.internal.util.array;
|
|
import core.stdc.string;
|
|
import core.stdc.stdlib;
|
|
debug(PRINTF) import core.stdc.stdio;
|
|
}
|
|
|
|
/**
|
|
* Keep for backward binary compatibility. This function can be removed in the future.
|
|
*/
|
|
extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
|
|
{
|
|
debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize);
|
|
|
|
immutable elementSize = ti.tsize;
|
|
|
|
// Need a temporary buffer tmp[] big enough to hold one element
|
|
void[16] buf = void;
|
|
void* ptmp = (elementSize > buf.sizeof) ? malloc(elementSize) : buf.ptr;
|
|
scope (exit)
|
|
{
|
|
if (ptmp != buf.ptr)
|
|
free(ptmp);
|
|
}
|
|
return _d_arrayassign_l(ti, from, to, ptmp);
|
|
}
|
|
|
|
/**
|
|
* Does array assignment (not construction) from another
|
|
* lvalue array of the same element type.
|
|
* Handles overlapping copies.
|
|
* Input:
|
|
* ti TypeInfo of the element type.
|
|
* dst Points target memory. Its .length is equal to the element count, not byte length.
|
|
* src Points source memory. Its .length is equal to the element count, not byte length.
|
|
* ptmp Temporary memory for element swapping.
|
|
*/
|
|
extern (C) void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp)
|
|
{
|
|
debug(PRINTF) printf("_d_arrayassign_l(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
|
|
|
|
immutable elementSize = ti.tsize;
|
|
|
|
enforceRawArraysConformable("copy", elementSize, src, dst, true);
|
|
|
|
if (src.ptr < dst.ptr && dst.ptr < src.ptr + elementSize * src.length)
|
|
{
|
|
// If dst is in the middle of src memory, use reverse order.
|
|
for (auto i = dst.length; i--; )
|
|
{
|
|
void* pdst = dst.ptr + i * elementSize;
|
|
void* psrc = src.ptr + i * elementSize;
|
|
memcpy(ptmp, pdst, elementSize);
|
|
memcpy(pdst, psrc, elementSize);
|
|
ti.postblit(pdst);
|
|
ti.destroy(ptmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Otherwise, use normal order.
|
|
foreach (i; 0 .. dst.length)
|
|
{
|
|
void* pdst = dst.ptr + i * elementSize;
|
|
void* psrc = src.ptr + i * elementSize;
|
|
memcpy(ptmp, pdst, elementSize);
|
|
memcpy(pdst, psrc, elementSize);
|
|
ti.postblit(pdst);
|
|
ti.destroy(ptmp);
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
unittest // Bugzilla 14024
|
|
{
|
|
string op;
|
|
|
|
struct S
|
|
{
|
|
char x = 'x';
|
|
this(this) { op ~= x-0x20; } // upper case
|
|
~this() { op ~= x; } // lower case
|
|
}
|
|
|
|
S[4] mem;
|
|
ref S[2] slice(int a, int b) { return mem[a .. b][0 .. 2]; }
|
|
|
|
op = null;
|
|
mem[0].x = 'a';
|
|
mem[1].x = 'b';
|
|
mem[2].x = 'x';
|
|
mem[3].x = 'y';
|
|
slice(0, 2) = slice(2, 4); // [ab] = [xy]
|
|
assert(op == "XaYb", op);
|
|
|
|
op = null;
|
|
mem[0].x = 'x';
|
|
mem[1].x = 'y';
|
|
mem[2].x = 'a';
|
|
mem[3].x = 'b';
|
|
slice(2, 4) = slice(0, 2); // [ab] = [xy]
|
|
assert(op == "XaYb", op);
|
|
|
|
op = null;
|
|
mem[0].x = 'a';
|
|
mem[1].x = 'b';
|
|
mem[2].x = 'c';
|
|
slice(0, 2) = slice(1, 3); // [ab] = [bc]
|
|
assert(op == "BaCb", op);
|
|
|
|
op = null;
|
|
mem[0].x = 'x';
|
|
mem[1].x = 'y';
|
|
mem[2].x = 'z';
|
|
slice(1, 3) = slice(0, 2); // [yz] = [xy]
|
|
assert(op == "YzXy", op);
|
|
}
|
|
|
|
/**
|
|
* Does array assignment (not construction) from another
|
|
* rvalue array of the same element type.
|
|
* Input:
|
|
* ti TypeInfo of the element type.
|
|
* dst Points target memory. Its .length is equal to the element count, not byte length.
|
|
* src Points source memory. Its .length is equal to the element count, not byte length.
|
|
* It is always allocated on stack and never overlapping with dst.
|
|
* ptmp Temporary memory for element swapping.
|
|
*/
|
|
extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp)
|
|
{
|
|
debug(PRINTF) printf("_d_arrayassign_r(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
|
|
|
|
immutable elementSize = ti.tsize;
|
|
|
|
enforceRawArraysConformable("copy", elementSize, src, dst, false);
|
|
|
|
// Always use normal order, because we can assume that
|
|
// the rvalue src has no overlapping with dst.
|
|
foreach (i; 0 .. dst.length)
|
|
{
|
|
void* pdst = dst.ptr + i * elementSize;
|
|
void* psrc = src.ptr + i * elementSize;
|
|
memcpy(ptmp, pdst, elementSize);
|
|
memcpy(pdst, psrc, elementSize);
|
|
ti.destroy(ptmp);
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
/**
|
|
* Do assignment to an array.
|
|
* p[0 .. count] = value;
|
|
*/
|
|
extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
|
|
{
|
|
void* pstart = p;
|
|
|
|
auto element_size = ti.tsize;
|
|
|
|
// Need a temporary buffer tmp[] big enough to hold one element
|
|
immutable maxAllocaSize = 512;
|
|
void *ptmp = (element_size > maxAllocaSize) ? malloc(element_size) : alloca(element_size);
|
|
|
|
foreach (i; 0 .. count)
|
|
{
|
|
memcpy(ptmp, p, element_size);
|
|
memcpy(p, value, element_size);
|
|
ti.postblit(p);
|
|
ti.destroy(ptmp);
|
|
p += element_size;
|
|
}
|
|
if (element_size > maxAllocaSize)
|
|
free(ptmp);
|
|
return pstart;
|
|
}
|