This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

compiler warning in function with embedded assembly

Note: This was originally posted on 9th May 2012 at http://forums.arm.com

I'm using inline ARM assembly in C++ functions and I was wondering how to avoid "control reaches end of non-void function" warnings when my code is storing the final value in R0.

For example this function works fine, but the compiler will raise the warning:


int Math::test_iadd(int a, int B)
{  
  __asm volatile
(
  "add r0, %0, %1   \n\t"

  :
  : "r" (a), "r" (B)
  : "r0"
);
}

An easy fix is rewriting the function as:


int Math::test_iadd2(int a, int B)
{
int ret;

__asm volatile
(
  "add %0, %1, %2   \n\t"

  : "=r" (ret)
  : "r" (a), "r" (B)
  : "r0"
);


return ret;
}

But this shouldn't be required as the assembly generated by the compiler is basically the same code I use in the former function.

Any suggestion?
  • Note: This was originally posted on 10th May 2012 at http://forums.arm.com


    I could be wrong, but I believe that this code does not actually guarantee that the output ends up in r0. The register identities in the assembler are symbolic rather than actual register names, and I'm not sure how they actually get resolved to real registers. It's the logical output however, so it happens to work.
    Your second function is certainly the way I would write the return code.

    returning the value in R0 is defined in the AAPCS (ARM Architecture Procedure Call Standard) and even if R0 is just an alias for a physical register the mapping should be transparent to the coder.

    I do agree with spachner as the problem is generated by the C++ compiler, but I was wondering if there was a way to suppress it mixing ASM and C++, anyway better safe than sorry, so I'd go for the code style used in the second function, cheers.
  • Note: This was originally posted on 11th May 2012 at http://forums.arm.com


      Yes, but you are assuming the compiler (which parses the inline assembler and can shove it through the optimizer) actually assigns the "real" r0 to the symbolic r0 in your program and hasn't reordered any of the instructions in the instruction stream.

    I am, cause the volatile keyword should prevent that.
  • Note: This was originally posted on 10th May 2012 at http://forums.arm.com

    I would say the warning is produced by the C compiler which does not recognize what you are doing in the assembler statements. So a missing return will throw the warning.

    spachner
  • Note: This was originally posted on 10th May 2012 at http://forums.arm.com

    I could be wrong, but I believe that this code does not actually guarantee that the output ends up in r0. The register identities in the assembler are symbolic rather than actual register names, and I'm not sure how they actually get resolved to real registers. It's the logical output however, so it happens to work.
    Your second function is certainly the way I would write the return code.
  • Note: This was originally posted on 10th May 2012 at http://forums.arm.com

    [color=#222222][size=2]
    returning the value in R0 is defined in the AAPCS
    [/size][/color]
    [color=#222222][size=2]
    [/size][/color]
    [color=#222222][size=2]Yes, but you are assuming the compiler (which parses the inline assembler and can shove it through the optimizer) actually assigns the "real" r0 to the symbolic r0 in your program and hasn't reordered any of the instructions in the instruction stream.[/size][/color]
    [color=#222222][size=2]
    [/size][/color]
    [color=#222222][size=2]In this case it happens to work because the output of the function is trivial, so the compiler has been sensible, but for a more complex "non trivial" example I'm not sure what guarantees you get from the compiler in terms of it deciding to reallocate registers to something it deems more optimal.[/size][/color]
    [size=2]
    [/size]