Thread overview
Infinite recursion with memcpy and memset/memclr lowerings
Jul 19
kinke
July 19
I ran into an interesting situation with my ARM Cortex-M experiment using LDC.

I have this function:

extern(C) void* __aeabi_memclr(void* dest, size_t num)
{
    byte* d = cast(byte*)dest;
    for(int i = 0; i < num; i++)
    {
        d[i] = cast(byte)0;
    }

    return dest;
}

LDC seems to recognize the body of the function and rewrites it as `__aeabi_memclr`, causing infinite recursion.  Is there some way I can instruct the compiler to stop doing that?

Mike
July 19
On Thursday, 19 July 2018 at 12:12:28 UTC, Mike Franklin wrote:
> I ran into an interesting situation with my ARM Cortex-M experiment using LDC.
>
> I have this function:
>
> extern(C) void* __aeabi_memclr(void* dest, size_t num)
> {
>     byte* d = cast(byte*)dest;
>     for(int i = 0; i < num; i++)
>     {
>         d[i] = cast(byte)0;
>     }
>
>     return dest;
> }
>
> LDC seems to recognize the body of the function and rewrites it as `__aeabi_memclr`, causing infinite recursion.  Is there some way I can instruct the compiler to stop doing that?
>
> Mike

Related: https://users.rust-lang.org/t/--aeabi-memclr-compiling-to-suicide-loop/4451

I don't know how to prevent LLVM from assuming the compiler-rt builtins are available.

If you don't insist on implementing everything yourself, you could use LLVM's implementations in compiler-rt, e.g., by a simple forward declaration or by using the LLVM memset intrinsic (see ldc.intrinsics) and obviously linking against the compiler-rt builtins lib (e.g., https://github.com/llvm-mirror/compiler-rt/blob/master/lib/builtins/arm/aeabi_memset.S).
July 19
On Thursday, 19 July 2018 at 12:12:28 UTC, Mike Franklin wrote:
>
> LDC seems to recognize the body of the function and rewrites it as `__aeabi_memclr`, causing infinite recursion.  Is there some way I can instruct the compiler to stop doing that?

You can use `-disable-simplify-libcalls`.

Looks like we need to implement something equivalent to Clang's `-fno-builtin` or `-ffreestanding` etc.  After some quick research, I don't think it is currently possible to disable these optimizations just for one function, can only disable it for one compiler invoke.

-Johan

July 19
On Thursday, 19 July 2018 at 14:51:02 UTC, kinke wrote:
> Related: https://users.rust-lang.org/t/--aeabi-memclr-compiling-to-suicide-loop/4451
>
> I don't know how to prevent LLVM from assuming the compiler-rt builtins are available.
>
> If you don't insist on implementing everything yourself, you could use LLVM's implementations in compiler-rt, e.g., by a simple forward declaration or by using the LLVM memset intrinsic (see ldc.intrinsics) and obviously linking against the compiler-rt builtins lib (e.g., https://github.com/llvm-mirror/compiler-rt/blob/master/lib/builtins/arm/aeabi_memset.S).

Correct me if I'm wrong, but it appears that forwarding to compiler-rt's implementation or using `ldc.intrinsics` will require linking in a C standard library.  I'd prefer to avoid that.

Mike
July 19
On Thursday, 19 July 2018 at 18:49:07 UTC, Johan Engelen wrote:

> You can use `-disable-simplify-libcalls`.

Thanks! That fixes things for now.

Mike
July 20
On Thursday, 19 July 2018 at 22:36:37 UTC, Mike Franklin wrote:

> Correct me if I'm wrong, but it appears that forwarding to compiler-rt's implementation or using `ldc.intrinsics` will require linking in a C standard library.  I'd prefer to avoid that.

FYI, I tried to implement my own `memcpy` and `memset` implementations and just have `__aeabi_memcpy` and `__aeabi_memclr` forward to those, but then the compiler recognized the `memcpy` and `memset` calls and replaced them with `__aeabi_memcpy` and `__aeabi_memclr`.  :-/

Mike

July 21
On 20 Jul 2018, at 2:35, Mike Franklin via digitalmars-d-ldc wrote:
> FYI, I tried to implement my own `memcpy` and `memset` implementations and just have `__aeabi_memcpy` and `__aeabi_memclr` forward to those, but then the compiler recognized the `memcpy` and `memset` calls and replaced them with `__aeabi_memcpy` and `__aeabi_memclr`.  :-/

Yep, this is expected behaviour without something like `-fno-builtin` or `-disable-simplify-libcalls`. C runtime libraries (glibc/compiler-rt…) are of course in exactly the same situation with GCC/Clang.

 — David