Jump to page: 1 2
Thread overview
Naked functions
Jul 23, 2018
Jack Applegame
Jul 23, 2018
David Nadlinger
Jul 25, 2018
Jack Applegame
Jul 27, 2018
Jack Applegame
Jul 27, 2018
Jack Applegame
Jul 27, 2018
kinke
Jul 27, 2018
Jack Applegame
Jul 27, 2018
Jack Applegame
Jul 27, 2018
kinke
Jul 27, 2018
kinke
Jul 27, 2018
Jack Applegame
July 23, 2018
Hello.
How to define a naked function on the ARM platform?

> asm {
>    naked;
> }

doesn't work.
July 24, 2018
Hi Jack,

On 23 Jul 2018, at 23:06, Jack Applegame via digitalmars-d-ldc wrote:
>> asm {
>>    naked;
>> }
>
> doesn't work.

asm {} is the x86-only DMD syntax.

See https://github.com/ldc-developers/ldc/pull/2773 which adds a @naked attribute; it would to great to hear whether this fits your use case.

 — David
July 25, 2018
On Monday, 23 July 2018 at 23:36:01 UTC, David Nadlinger wrote:
> Hi Jack,
>
> On 23 Jul 2018, at 23:06, Jack Applegame via digitalmars-d-ldc wrote:
>>> asm {
>>>    naked;
>>> }
>>
>> doesn't work.
>
> asm {} is the x86-only DMD syntax.
>
> See https://github.com/ldc-developers/ldc/pull/2773 which adds a @naked attribute; it would to great to hear whether this fits your use case.
>
>  — David

It works. Thanks.
July 27, 2018
On Monday, 23 July 2018 at 23:36:01 UTC, David Nadlinger wrote:
> Hi Jack,
>
> On 23 Jul 2018, at 23:06, Jack Applegame via digitalmars-d-ldc wrote:
>>> asm {
>>>    naked;
>>> }
>>
>> doesn't work.
>
> asm {} is the x86-only DMD syntax.
>
> See https://github.com/ldc-developers/ldc/pull/2773 which adds a @naked attribute; it would to great to hear whether this fits your use case.
>
>  — David

There is one strange thing.
Should  the compiler to insert the return command for naked functions?
I suppose it shouldn't.

For example:

naked.cpp
> __attribute__ ((naked)) int sum(int a, int b) {
>     return a + b;
> }

> $ arm-none-eabi-gcc -c naked.cpp -O3 -o naked_cpp.o
> $ arm-none-eabi-objdump -d naked_cpp.o

> 00000000 <_Z3sumii>:
>   0:   e0800001        add     r0, r0, r1


naked.d
> @naked int sum(int a, int b) {
>     return a + b;
> }

> $ ldc2 -c -mtriple=thumb-none-linux-eabi -mcpu=cortex-m3 -O3 naked.d -of naked_d.o
> $ arm-none-eabi-objdump -d naked_d.o

> 00000000 <_D5naked3sumFiiZi>:
>   0:   4408            add     r0, r1
>   2:   4770            bx      lr     <------- WHY???


Looks like LDC removes the prologue/epilogue, but not completely, leaving the return from function.


July 27, 2018
> $ arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb naked.cpp -O3 -o naked_cpp.o

generates

> 00000000 <_Z3sumii>:
>   0:   4408            add     r0, r1
>   2:   bf00            nop

July 27, 2018
On Friday, 27 July 2018 at 10:11:03 UTC, Jack Applegame wrote:
> There is one strange thing.
> Should  the compiler to insert the return command for naked functions?
> I suppose it shouldn't.
>
> [...]
>
> Looks like LDC removes the prologue/epilogue, but not completely, leaving the return from function.

In this case I'd think it has to, you're even using an explicit return statement. I'm not familiar with the ARM calling convention wrt. call/return, but gcc emitting no return seems very strange (where is it supposed to continue after the add instruction? the next function in the final binary?!). Did you test that it actually works as intended?

I updated the PR yesterday, so that LDC's pro-/epilogue is excluded too, which allows the usage of params (not just in some cases like yours together with -O). [Your sample doesn't work anymore now, crashing the compiler, as it now requires __asm() and/or inlineIR() to work with params.]

AFAIK, a return is required as we go through LLVM IR and not directly to the assembler (which for example allows you to write the function body in LLVM IR). Yesterday's variant probably crashes if there's no explicit return (e.g., with __asm() and a naked function returning void).

I take it this is just a toy example for gcc/LDC comparison, or do you really need to omit a return instruction in real-world code?
July 27, 2018
On Friday, 27 July 2018 at 17:53:51 UTC, kinke wrote:
> On Friday, 27 July 2018 at 10:11:03 UTC, Jack Applegame wrote:
>> There is one strange thing.
>> Should  the compiler to insert the return command for naked functions?
>> I suppose it shouldn't.
>>
>> [...]
>>
>> Looks like LDC removes the prologue/epilogue, but not completely, leaving the return from function.
>
> In this case I'd think it has to, you're even using an explicit return statement. I'm not familiar with the ARM calling convention wrt. call/return, but gcc emitting no return seems very strange (where is it supposed to continue after the add instruction? the next function in the final binary?!). Did you test that it actually works as intended?
>
> I updated the PR yesterday, so that LDC's pro-/epilogue is excluded too, which allows the usage of params (not just in some cases like yours together with -O). [Your sample doesn't work anymore now, crashing the compiler, as it now requires __asm() and/or inlineIR() to work with params.]
>
> AFAIK, a return is required as we go through LLVM IR and not directly to the assembler (which for example allows you to write the function body in LLVM IR). Yesterday's variant probably crashes if there's no explicit return (e.g., with __asm() and a naked function returning void).

My example is incorrect.
Actually, GCC documentation recommends to use only basic assembly in naked functions and Clang completely disallows the use of anything other than asm statement. But both remove the return instruction.
Compare:
https://godbolt.org/g/yVzpPx
https://godbolt.org/g/fe9pNY


> I take it this is just a toy example for gcc/LDC comparison, or do you really need to omit a return instruction in real-world code?

I'm trying to write a simple kernel with multithreading support on bare metal (Cortex-M3). In the context switching function, the compiler-inserted return is unnecessary, but not a problem.
July 27, 2018
This code

> import ldc.llvmasm;
> @naked void foo() {
>   __asm("mov lr, 0xfffffffd", "");
> }

Definitely should compile to

> mvn.w   lr, #2

But now it compiles to

> mvn.w   lr, #2
> bx      lr

July 27, 2018
On Friday, 27 July 2018 at 19:34:49 UTC, Jack Applegame wrote:
> This code
>
>> import ldc.llvmasm;
>> @naked void foo() {
>>   __asm("mov lr, 0xfffffffd", "");
>> }
>
> Definitely should compile to
>
>> mvn.w   lr, #2
>
> But now it compiles to
>
>> mvn.w   lr, #2
>> bx      lr

'Now' (current/yesterday's PR), this crashes the compiler for the aforementioned reason. Interestingly, clang also goes through IR (see -emit-llvm and compare with LDC's -output-ll output) but appends an unreachable at the end, which gets rid of the error about non-terminated function. I've just implemented this, but the unreachable makes it to the final assembly, whereas it vanishes at some point for clang.
July 27, 2018
On Friday, 27 July 2018 at 20:17:12 UTC, kinke wrote:
> I've just implemented this, but the unreachable makes it to the final assembly, whereas it vanishes at some point for clang.

Ah wait, that remaining unreachable is apparently Windows-specific and vanishes for Linux.
« First   ‹ Prev
1 2