wrong assembly generated for volatile variables in naked function
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
GNU Arm Embedded Toolchain |
New
|
Undecided
|
Unassigned |
Bug Description
Hello,
I'm using the GNU ARM Embedded Toolchain 6-2017-q2-update. I have a naked function (needed for ISR processing), which calls an inline function.
The file is compiled with the following command:
arm-none-
Here is the file content (test.c):
// ISR macros shrinked to the minimum for the issue
#define ISR_ENTER_M() asm volatile ( "PUSH {R0-R12, LR} \n\t" );
#define ISR_LEAVE_M() asm volatile ( "POP {R0-R12, LR} \n\t" );
inline void test_inline_wait ( int ctr ) __attribute__ ((__always_
void test_naked_func ( void ) __attribute__ ((naked));
inline void test_inline_wait ( int ctr )
{
// As this is an inline function and the project is compiled with
// the optimization -Os the counter variable i must be defined as volatile
// so that the wait loop won't be removed by the compiler.
volatile int i = ctr;
while ( i-- > 0 ) ;
}
void test_naked_func ( void )
{
ISR_ENTER_M();
// Do some interrupt handling here
test_inline_wait ( 100 );
ISR_LEAVE_M();
}
I have actually two problems:
1. If I compile the file with the optimization option -O0 (no optimization), the I get the following error:
"test.c: In function 'test_naked_func':
test.c:21:16: error: cannot allocate stack for variable 'i', naked function.
volatile int i = ctr;"
2. With the optimization option -Os the file can be compiled without any errors / warnings. The generated assembly is wrong, because it overwrites the stack! Here is the listing for the option -Os:
26:test.c **** void test_naked_func ( void )
27:test.c **** {
25 .loc 1 27 0
26 .cfi_startproc
27
28
29
28:test.c **** ISR_ENTER_M();
30 .loc 1 28 0
31 .syntax unified
32
33 0000 2DE9FF5F PUSH {R0-R12,LR}
34
35
36 .LVL0:
37 .thumb
38 .syntax unified
39 .LBB4:
40 .LBB5:
21:test.c **** while ( i-- > 0 ) ;
41 .loc 1 21 0
42 0004 6423 movs r3,#100
43 0006 0193 str r3,[sp,#4]
44 .L2:
22:test.c **** }
45 .loc 1 22 0
46 0008 019B ldr r3,[sp,#4]
47 000a 5A1E subs r2,r3,#1
48 000c 002B cmp r3,#0
49 000e 0192 str r2,[sp,#4]
50 0010 FADC bgt .L2
51 .LVL1:
52 .LBE5:
53 .LBE4:
29:test.c **** // Do some interrupt handling here
30:test.c ****
31:test.c **** test_inline_wait ( 100 );
32:test.c ****
33:test.c **** ISR_LEAVE_M();
54 .loc 1 33 0
55 .syntax unified
56
57 0012 BDE8FF5F POP {R0-R12,LR}
58
59
34:test.c **** }
The compiler adds the instruction "str r3,[sp,#4]", which overwrites the current stack. No stack memory is reserved at the beginning of the function. Usually, in a non-naked function the compiler will add the instruction "sub sp, sp, 8" at the beginning of the function and then do the stack access "str r3,[sp,#4]". In this case wrong assembly output is generated.
I newly switched from an older toolchain (5.3 2016q1) to the toolchain 6-2017-q2-update (due to bug #1667509). With the toolchain 5.3 I can compile my test file with both options -Os and -O0. In both cases the instruction "str r3,[sp,#4]" is not generated so that the stack is not corrupted.
Test file test.c added