January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | On Tuesday, 31 January 2017 at 10:00:03 UTC, Stefan Koch wrote:
> On Tuesday, 31 January 2017 at 09:31:23 UTC, Nordlöw wrote:
>>
>> How can we be sure that the return value points to the same content as `s1`?
> Because of the return attribute.
> return means I am passing this value through myself.
I thought it meant "the parameter can be returned" not "the parameter *will* be returned".
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Olivier FAURE | On Tuesday, 31 January 2017 at 10:20:59 UTC, Olivier FAURE wrote:
> I thought it meant "the parameter can be returned" not "the parameter *will* be returned".
And what about multiple `return`-qualified function parameters?
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Olivier FAURE | On Tuesday, 31 January 2017 at 10:17:09 UTC, Olivier FAURE wrote:
> On Tuesday, 31 January 2017 at 01:30:48 UTC, Walter Bright wrote:
>> 3. Nothing s2 transitively points to is altered via s2.
>
> Wait, really? Does that mean that this code is implicitly illegal?
>
> import core.stdc.string;
>
> void main()
> {
> int*[10] data1;
> int*[10] data2;
>
> memcpy(data1.ptr, data2.ptr, 10);
> }
>
> Since memcpy is @system, I have no way to know for sure (the compiler obviously won't warn me since I can't mark main as @safe), so I'd argue the prototype doesn't carry that information.
Point 3 is about `const`, which as far as I know is unaffected by application of @safe. Did you mean to quote a different point?
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, 31 January 2017 at 01:30:48 UTC, Walter Bright wrote: > Just from D's type signature, we can know a lot about memcpy(): > > 1. There are no side effects. > 2. The return value is derived from s1. > 3. Nothing s2 transitively points to is altered via s2. > 4. Copies of s1 or s2 are not saved. > > The C declaration does not give us any of that info, although the C description > does give us 2, and the 'restrict' says that s1 and s2 do not overlap. > > The Rust declaration does not give us 1, 2 or 4 (because it is marked as unsafe). If it was safe, the declaration does not give us 2. > > By this information being knowable from the declaration, the compiler knows it too and can make use of it. Well, I would not have taken memcpy as an example in favor of D. Good C compilers (like gcc) know what memcpy does and are able to optimize it according to its arguments. DMD may know better about memcpy through its declaration but does not make any use about it. A simple example: // cmemcpy.c #include <string.h> #include <stdio.h> int main(void) { char a[16] = "world hello"; char b[16] = ""; memcpy(b, a, 12); memcpy(b, a + 6, 5); memcpy(b + 6, a, 5); printf("%s -> %s\n", a, b); } //------------ gcc -Ofast produces the following code: main: .LFB0: .cfi_startproc subq $40, %rsp .cfi_def_cfa_offset 48 movl $.LC0, %edi movabsq $7307126011096887159, %rax movq %rax, (%rsp) movq %rsp, %rdx movq %rax, 16(%rsp) leaq 16(%rsp), %rsi movq $7302252, 24(%rsp) movl 22(%rsp), %eax movq $0, 8(%rsp) movl $7302252, 8(%rsp) movl %eax, (%rsp) movzbl 26(%rsp), %eax movb %al, 4(%rsp) movl 16(%rsp), %eax movl %eax, 6(%rsp) movzbl 20(%rsp), %eax movb %al, 10(%rsp) xorl %eax, %eax call printf xorl %eax, %eax addq $40, %rsp .cfi_def_cfa_offset 8 ret No call to memcpy, this has been optimized out by the compiler. Now a D equivalent: // dmemcpy.d module dmemcpy; import core.stdc.string, std.stdio; void main() { char [16] a_ = "world hello", b_ = ""; void* a = &a_[0], b = &b_[0]; memcpy(b, a, 12); memcpy(b, a + 6, 5); memcpy(b + 6, a, 5); writefln("%s -> %s", a_, b_); } //-------------------- dmd -O -release -inline -boundscheck=off prouces the following asm: _Dmain: push RBP mov RBP,RSP sub RSP,020h lea RSI,_TMP0@PC32[RIP] lea RDI,-020h[RBP] movsd movsd lea RSI,_TMP0@PC32[RIP] lea RDI,-010h[RBP] movsd movsd mov EDX,0Ch lea RSI,-020h[RBP] lea RDI,-010h[RBP] call memcpy@PLT32 mov EDX,5 lea RSI,-01Ah[RBP] lea RDI,-010h[RBP] call memcpy@PLT32 mov EDX,5 lea RSI,-020h[RBP] lea RDI,-0Ah[RBP] call memcpy@PLT32 lea RDX,_TMP0@PC32[RIP] mov EDI,8 mov RSI,RDX push dword ptr -018h[RBP] push dword ptr -020h[RBP] push dword ptr -8[RBP] push dword ptr -010h[RBP] call _D3std5stdio27__T8writeflnTAyaTG16aTG16aZ8writeflnFNfAyaG16aG16aZv@PLT32 add RSP,020h xor EAX,EAX mov RSP,RBP pop RBP ret So with DMD, calls to memcpy are done verbatim, without any optimization :-( To be fair, gdc will optimize the memcpy call out too. But, my main argument here, is that a good C compiler, is able to do a very good job at optimizing memcpy, so the extra information brought by the D language, is not so useful in practice. |
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard Delorme | On Tuesday, 31 January 2017 at 13:50:33 UTC, Richard Delorme wrote:
> But, my main argument here, is that a good C compiler, is able to do a very good job at optimizing memcpy, so the extra information brought by the D language, is not so useful in practice.
The point of Walter's argument was not about performance but, safety guarantees. Guarantees which cannot be given by C, or by Rust due to it's marking as unsafe (as I understand it). So the extra info is very useful for the programmer.
Also, I would compare apples to apples here and compile both the C program and the D code with LLVM.
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | On Tuesday, 31 January 2017 at 10:00:03 UTC, Stefan Koch wrote:
> Because of the return attribute.
> return means I am passing this value through myself.
Ahh, missed that. My mistake.
Thanks, Walter!
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Tuesday, 31 January 2017 at 11:32:01 UTC, John Colvin wrote:
> On Tuesday, 31 January 2017 at 10:17:09 UTC, Olivier FAURE wrote:
>> On Tuesday, 31 January 2017 at 01:30:48 UTC, Walter Bright wrote:
>
> Point 3 is about `const`, which as far as I know is unaffected by application of @safe. Did you mean to quote a different point?
Oh yeah, I thought it was about scope. Makes sense then.
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike | On Tuesday, 31 January 2017 at 02:18:23 UTC, Mike wrote: > On Tuesday, 31 January 2017 at 02:01:05 UTC, Walter Bright wrote: >> On 1/30/2017 5:53 PM, Mike wrote: >>> One in particular prevents me from using D, period! - >>> https://issues.dlang.org/show_bug.cgi?id=14758 >> >> The -betterC switch is the approach we intend to take to deal with that issue. > > I recommend against that; it's too blunt of an instrument. Instead I suggest following through on things like https://issues.dlang.org/show_bug.cgi?id=12270 and considering this proposal (http://forum.dlang.org/post/psssnzurlzeqeneagora@forum.dlang.org) instead. > > Mike The main problem - the opaque extern (C) interface an therefore non-lazy code generation - is already being worked on: http://forum.dlang.org/thread/o0kdnp$2i2t$1@digitalmars.com http://forum.dlang.org/thread/wbtjswiwbrtxzqiorwiw@forum.dlang.org |
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, 31 January 2017 at 01:30:48 UTC, Walter Bright wrote:
> 2. The return value is derived from s1.
> 4. Copies of s1 or s2 are not saved.
Actually I didn't know either of those things from looking at the signature because DIP25 and DIP1000 have marketing problems, in that the only way to get info on them is on the DIP pages. I'd be willing to bet money that 80% of the people who use D don't know about the -dip25 flag.
Is there anywhere which gives a simple explaination of both of these DIP's safety checks?
|
January 31, 2017 Re: memcpy() comparison: C, Rust, and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard Delorme | On 1/31/2017 5:50 AM, Richard Delorme wrote:
> Well, I would not have taken memcpy as an example in favor of D. Good C
> compilers (like gcc) know what memcpy does and are able to optimize it according
> to its arguments. DMD may know better about memcpy through its declaration but
> does not make any use about it.
That may be true, but is not my point. The compiler cannot have built in knowledge of every function. I just used memcpy() as an example because it is extremely well known.
As for making use of the type signature information, DMD uses it to check the memory safety of arguments supplied to memcpy(), something gcc does not do.
|
Copyright © 1999-2021 by the D Language Foundation