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

Morello GNU g++ Compiler bug? - Inline assembler in template function ignores register declarations

Hi

Potential GCC bug? - please advise if this is a known issue, if not please inform how to raise an issue on the Gnu toolchain for Morello.

Issue: When defining register variables in a template function, the compiler ignores the directives.  Does not happen if not using templates.

Found on: ARM GNU Toolchain for Morello release.  Applies to Linux hybrid-cap or Linux pure-cap.
- Note: This behaviour does not apply when using clang.

Example Code Snippet

Note: This is based on Arm Morello compartment demo.
Intent is to call into a function following C calling convention, with C0...C6 set to passed in arguments:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdint.h>
extern uintcap_t AsUintcap(uint32_t);
template <typename Fn>
inline void TestCall(uint32_t id,
uintcap_t arg0, uintcap_t arg1, uintcap_t arg2,
uintcap_t arg3, uintcap_t arg4, uintcap_t arg5,
Fn arg6)
{
register uintcap_t c0 asm("c0") = AsUintcap(id);
register uintcap_t c1 asm("c1") = arg0;
register uintcap_t c2 asm("c2") = arg1;
register uintcap_t c3 asm("c3") = arg2;
register uintcap_t c4 asm("c4") = arg3;
register uintcap_t c5 asm("c5") = arg4;
register uintcap_t c6 asm("c6") = arg5;
asm __volatile__("blr %[fn]\n"
: : [fn] "C"(arg6), "C"(c0), "C"(c1), "C"(c2), "C"(c3), "C"(c4), "C"(c5), "C"(c6)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Compile with g++ -march=morello -save-temps -Wall -Wextra -O3 -std=gnu++14 -c test.cpp  (Note: different optimisation levels give same failure behaviour).

Resulting generated assembler (tidied - comment added is mine):

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
stp x29, x30, [sp, -128]!
mov x29, sp
str c7, [sp, 16]
stp c6, c5, [sp, 32]
str c2, [sp, 96]
str c1, [sp, 112]
stp c4, c3, [sp, 64]
bl _Z9AsUintcapj
ldr c14, [sp, 112]
ldp c2, c6, [sp, 16]
ldp c8, c4, [sp, 48]
ldp c10, c12, [sp, 80]
// Args passed as c0, c14, c4, c6, c8, c10, c12
// c2 corrupted; being used for branch address
blr c2
ldp x29, x30, [sp], 128
ret
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Compare result if not using a template function (modify example code by removing template statement and add using Fn=void *__capability;):

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
stp x29, x30, [sp, -128]!
mov x29, sp
str c7, [sp, 16]
stp c6, c5, [sp, 32]
stp c4, c3, [sp, 64]
stp c2, c1, [sp, 96]
bl _Z9AsUintcapj
ldr c8, [sp, 16]
ldp c6, c5, [sp, 32]
ldp c4, c3, [sp, 64]
ldp c2, c1, [sp, 96]
// c0..c6 set correctly as defined arguments.
// c8 is used for address; no corruption of registers we are using
blr c8
ldp x29, x30, [sp], 128
ret
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 

Thanks
Pete

0